diff options
Diffstat (limited to 'test/SemaCXX')
87 files changed, 3882 insertions, 667 deletions
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp index 3634fa346272..6a48f36801bd 100644 --- a/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -1,6 +1,10 @@ // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions +typedef unsigned short char16_t; +typedef unsigned int char32_t; + +typename decltype(3) a; // expected-warning {{expected a qualified name after 'typename'}} namespace ms_conversion_rules { diff --git a/test/SemaCXX/MicrosoftCompatibilityNoExceptions.cpp b/test/SemaCXX/MicrosoftCompatibilityNoExceptions.cpp new file mode 100644 index 000000000000..d932b5dbbcea --- /dev/null +++ b/test/SemaCXX/MicrosoftCompatibilityNoExceptions.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-compatibility + +// PR13153 +namespace std {} +class type_info {}; +void f() { + (void)typeid(int); +} diff --git a/test/SemaCXX/PR10243.cpp b/test/SemaCXX/PR10243.cpp index 129ff80e2d2e..19a8b04e84fa 100644 --- a/test/SemaCXX/PR10243.cpp +++ b/test/SemaCXX/PR10243.cpp @@ -9,12 +9,12 @@ struct T0 { struct T1 { S s; // expected-error{{field has incomplete type 'S'}} - T1(T1&) = default; + T1(const T1&) = default; }; struct T2 { S s; // expected-error{{field has incomplete type 'S'}} - T2& operator=(T2&) = default; + T2& operator=(const T2&) = default; }; struct T3 { diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index b164d9eda6a5..e20a89009bd9 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -259,3 +259,17 @@ namespace pr9247 { }; }; } + +namespace pr12658 { + class C {
+ public:
+ C(int v){}
+ virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f' in 'C'}}
+ };
+
+ void foo( C& c ) {}
+
+ void bar( void ) {
+ foo(C(99)); // expected-error {{allocating an object of abstract class type 'pr12658::C'}}
+ } +} diff --git a/test/SemaCXX/address-of-temporary.cpp b/test/SemaCXX/address-of-temporary.cpp index eb5dee50598e..bb6cba3187f5 100644 --- a/test/SemaCXX/address-of-temporary.cpp +++ b/test/SemaCXX/address-of-temporary.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-error=address-of-temporary -verify %s -struct X { +// RUN: %clang_cc1 -fsyntax-only -Wno-error=address-of-temporary -verify -std=gnu++11 %s +struct X { X(); X(int); X(int, int); @@ -10,3 +10,39 @@ void f1() { (void)&X(1); } // expected-warning{{taking the address of a temporar void f2() { (void)&X(1, 2); } // expected-warning{{taking the address of a temporary object}} void f3() { (void)&(X)1; } // expected-warning{{taking the address of a temporary object}} + +namespace PointerToArrayDecay { + struct Y { + int a[4]; + }; + + typedef int A[4]; + + template<typename T> void consume(T); + struct S { int *p; }; + + void g0() { int *p = Y().a; } // expected-warning{{pointer is initialized by a temporary array}} + void g1() { int *p = Y{}.a; } // expected-warning{{pointer is initialized by a temporary array}} + void g2() { int *p = A{}; } // expected-warning{{pointer is initialized by a temporary array}} + void g3() { int *p = (A){}; } // expected-warning{{pointer is initialized by a temporary array}} + + void h0() { consume(Y().a); } + void h1() { consume(Y{}.a); } + void h2() { consume(A{}); } + void h3() { consume((A){}); } + + void i0() { S s = { Y().a }; } // expected-warning{{pointer is initialized by a temporary array}} + void i1() { S s = { Y{}.a }; } // expected-warning{{pointer is initialized by a temporary array}} + void i2() { S s = { A{} }; } // expected-warning{{pointer is initialized by a temporary array}} + void i3() { S s = { (A){} }; } // expected-warning{{pointer is initialized by a temporary array}} + + void j0() { (void)S { Y().a }; } + void j1() { (void)S { Y{}.a }; } + void j2() { (void)S { A{} }; } + void j3() { (void)S { (A){} }; } + + void k0() { consume(S { Y().a }); } + void k1() { consume(S { Y{}.a }); } + void k2() { consume(S { A{} }); } + void k3() { consume(S { (A){} }); } +} diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index 484dd3379ed7..4bf79f851e0b 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/test/SemaCXX/alias-template.cpp @@ -145,3 +145,30 @@ namespace Curried { template<typename T, typename U> struct S; template<typename T> template<typename U> using SS = S<T, U>; // expected-error {{extraneous template parameter list in alias template declaration}} } + +// PR12647 +namespace SFINAE { + template<bool> struct enable_if; // expected-note 2{{here}} + template<> struct enable_if<true> { using type = void; }; + + template<typename T> struct is_enum { static constexpr bool value = __is_enum(T); }; + + template<typename T> using EnableIf = typename enable_if<T::value>::type; // expected-error {{undefined template}} + template<typename T> using DisableIf = typename enable_if<!T::value>::type; // expected-error {{undefined template}} + + template<typename T> EnableIf<is_enum<T>> f(); + template<typename T> DisableIf<is_enum<T>> f(); + + enum E { e }; + + int main() { + f<int>(); + f<E>(); + } + + template<typename T, typename U = EnableIf<is_enum<T>>> struct fail1 {}; // expected-note {{here}} + template<typename T> struct fail2 : DisableIf<is_enum<T>> {}; // expected-note {{here}} + + fail1<int> f1; // expected-note {{here}} + fail2<E> f2; // expected-note {{here}} +} diff --git a/test/SemaCXX/altivec.cpp b/test/SemaCXX/altivec.cpp index 39421b7c40f4..9de1f04b697c 100644 --- a/test/SemaCXX/altivec.cpp +++ b/test/SemaCXX/altivec.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -faltivec -fno-lax-vector-conversions -triple powerpc-unknown-unknown -verify %s +// RUN: %clang_cc1 -faltivec -fno-lax-vector-conversions -triple powerpc-unknown-unknown -fcxx-exceptions -verify %s typedef int V4i __attribute__((vector_size(16))); @@ -76,3 +76,8 @@ namespace LValueToRValueConversions { vector float initFloat = (vector float)(Struct().f); // expected-error {{did you mean to call it}} vector int initInt = (vector int)(Struct().n); // expected-error {{did you mean to call it}} } + +void f() { + try {} + catch (vector pixel px) {} +}; diff --git a/test/SemaCXX/anonymous-union-cxx11.cpp b/test/SemaCXX/anonymous-union-cxx11.cpp new file mode 100644 index 000000000000..8e682ebcda3d --- /dev/null +++ b/test/SemaCXX/anonymous-union-cxx11.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s + +namespace PR12866 { + struct bar { + union { + int member; + }; + }; + + void foo( void ) { + (void)sizeof(bar::member); + } +} diff --git a/test/SemaCXX/array-bound-merge.cpp b/test/SemaCXX/array-bound-merge.cpp index 74f58fa12360..8fb2ec52a9ee 100644 --- a/test/SemaCXX/array-bound-merge.cpp +++ b/test/SemaCXX/array-bound-merge.cpp @@ -7,3 +7,5 @@ extern int b[10]; int b[]; extern int c[1]; int c[] = {1,2}; // expected-error {{excess elements in array initializer}} + +int d[1][]; // expected-error {{array has incomplete element type 'int []'}} diff --git a/test/SemaCXX/arrow-operator.cpp b/test/SemaCXX/arrow-operator.cpp index 6535a0a2f201..173ff729fc1b 100644 --- a/test/SemaCXX/arrow-operator.cpp +++ b/test/SemaCXX/arrow-operator.cpp @@ -36,3 +36,31 @@ void f() Line_Segment(node1->Location()); // expected-error {{not a structure or union}} } } + + +namespace arrow_suggest { + +template <typename T> +class wrapped_ptr { + public: + wrapped_ptr(T* ptr) : ptr_(ptr) {} + T* operator->() { return ptr_; } + void Check(); // expected-note {{'Check' declared here}} + private: + T *ptr_; +}; + +class Worker { + public: + void DoSomething(); + void Chuck(); +}; + +void test() { + wrapped_ptr<Worker> worker(new Worker); + worker.DoSomething(); // expected-error {{no member named 'DoSomething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}} + worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'}} + worker.Chuck(); // expected-error {{no member named 'Chuck' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean 'Check'?}} +} + +} // namespace arrow_suggest diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index 46568aabd677..f3d818a75f35 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 %s -verify -fsyntax-only class A { - void f() __attribute__((deprecated)); + void f() __attribute__((deprecated)); // expected-note 2 {{declared here}} void g(A* a); void h(A* a) __attribute__((deprecated)); - int b __attribute__((deprecated)); + int b __attribute__((deprecated)); // expected-note 2 {{declared here}} }; void A::g(A* a) @@ -26,7 +26,7 @@ void A::h(A* a) } struct B { - virtual void f() __attribute__((deprecated)); + virtual void f() __attribute__((deprecated)); // expected-note 4 {{declared here}} void g(); }; @@ -68,20 +68,20 @@ void f(D* d) { // Overloaded namespace members. namespace test1 { - void foo(int) __attribute__((deprecated)); + void foo(int) __attribute__((deprecated)); // expected-note {{declared here}} void test1() { foo(10); } // expected-warning {{deprecated}} - void foo(short) __attribute__((deprecated)); + void foo(short) __attribute__((deprecated)); // expected-note {{declared here}} void test2(short s) { foo(s); } // expected-warning {{deprecated}} void foo(long); void test3(long l) { foo(l); } struct A { - friend void foo(A*) __attribute__((deprecated)); + friend void foo(A*) __attribute__((deprecated)); // expected-note {{declared here}} }; void test4(A *a) { foo(a); } // expected-warning {{deprecated}} namespace ns { struct Foo {}; - void foo(const Foo &f) __attribute__((deprecated)); + void foo(const Foo &f) __attribute__((deprecated)); // expected-note {{declared here}} } void test5() { foo(ns::Foo()); // expected-warning {{deprecated}} @@ -91,9 +91,9 @@ namespace test1 { // Overloaded class members. namespace test2 { struct A { - void foo(int) __attribute__((deprecated)); + void foo(int) __attribute__((deprecated)); // expected-note 2 {{declared here}} void foo(long); - static void bar(int) __attribute__((deprecated)); + static void bar(int) __attribute__((deprecated)); // expected-note 3 {{declared here}} static void bar(long); void test2(int i, long l); @@ -120,12 +120,12 @@ namespace test2 { namespace test3 { struct A { void operator*(const A &); - void operator*(int) __attribute__((deprecated)); + void operator*(int) __attribute__((deprecated)); // expected-note {{declared here}} void operator-(const A &) const; }; void operator+(const A &, const A &); - void operator+(const A &, int) __attribute__((deprecated)); - void operator-(const A &, int) __attribute__((deprecated)); + void operator+(const A &, int) __attribute__((deprecated)); // expected-note {{declared here}} + void operator-(const A &, int) __attribute__((deprecated)); // expected-note {{declared here}} void test() { A a, b; @@ -143,9 +143,9 @@ namespace test4 { struct A { typedef void (*intfn)(int); typedef void (*unintfn)(unsigned); - operator intfn() __attribute__((deprecated)); + operator intfn() __attribute__((deprecated)); // expected-note {{declared here}} operator unintfn(); - void operator ()(A &) __attribute__((deprecated)); + void operator ()(A &) __attribute__((deprecated)); // expected-note {{declared here}} void operator ()(const A &); }; @@ -163,7 +163,7 @@ namespace test4 { namespace test5 { struct A { - operator int() __attribute__((deprecated)); + operator int() __attribute__((deprecated)); // expected-note 3 {{declared here}} operator long(); }; void test1(A a) { @@ -193,8 +193,8 @@ namespace test5 { // rdar://problem/8518751 namespace test6 { - enum __attribute__((deprecated)) A { - a0 + enum __attribute__((deprecated)) A { // expected-note {{declared here}} + a0 // expected-note {{declared here}} }; void testA() { A x; // expected-warning {{'A' is deprecated}} @@ -202,7 +202,7 @@ namespace test6 { } enum B { - b0 __attribute__((deprecated)), + b0 __attribute__((deprecated)), // expected-note {{declared here}} b1 }; void testB() { @@ -212,8 +212,8 @@ namespace test6 { } template <class T> struct C { - enum __attribute__((deprecated)) Enum { - c0 + enum __attribute__((deprecated)) Enum { // expected-note {{declared here}} + c0 // expected-note {{declared here}} }; }; void testC() { @@ -224,7 +224,7 @@ namespace test6 { template <class T> struct D { enum Enum { d0, - d1 __attribute__((deprecated)), + d1 __attribute__((deprecated)), // expected-note {{declared here}} }; }; void testD() { diff --git a/test/SemaCXX/attr-visibility.cpp b/test/SemaCXX/attr-visibility.cpp new file mode 100644 index 000000000000..05aa5a33c72e --- /dev/null +++ b/test/SemaCXX/attr-visibility.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class Element> +void foo() { +} +template <> + __attribute__((visibility("hidden"))) // expected-note {{previous attribute is here}} +void foo<int>(); + +template <> +void foo<int>(); + +template <> + __attribute__((visibility("default"))) // expected-error {{visibility does not match previous declaration}} +void foo<int>() { +} + +struct x3 { + static int y; +} __attribute((visibility("default"))); // expected-warning {{attribute 'visibility' after definition is ignored}} diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp index 2b3ab68848eb..f027186735b3 100644 --- a/test/SemaCXX/bool.cpp +++ b/test/SemaCXX/bool.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s // Bool literals can be enum values. enum { diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index 993f8e1d7761..ec5eb17b08f3 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -7,7 +7,7 @@ void test() { typedef int arr[10]; while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}} - while (int f()=0) ; // expected-warning {{interpreted as a function declaration}} expected-note {{initializer}} expected-error {{a function type is not allowed here}} + while (int f()=0) ; // expected-error {{a function type is not allowed here}} struct S {} s; if (s) ++x; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 4aee913277e5..a80eda416f4e 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -2,7 +2,7 @@ // C++ rules for ?: are a lot stricter than C rules, and have to take into // account more conversion options. -// This test runs in C++0x mode for the contextual conversion of the condition. +// This test runs in C++11 mode for the contextual conversion of the condition. struct ToBool { explicit operator bool(); }; @@ -328,3 +328,27 @@ namespace PR9236 { (void)(true ? (void*)0 : A()); // expected-error{{incompatible operand types}} } } + +namespace DR587 { + template<typename T> + const T *f(bool b) { + static T t1 = T(); + static const T t2 = T(); + return &(b ? t1 : t2); + } + struct S {}; + template const int *f(bool); + template const S *f(bool); + + extern bool b; + int i = 0; + const int ci = 0; + volatile int vi = 0; + const volatile int cvi = 0; + + const int &cir = b ? i : ci; + volatile int &vir = b ? vi : i; + const volatile int &cvir1 = b ? ci : cvi; + const volatile int &cvir2 = b ? cvi : vi; + const volatile int &cvir3 = b ? ci : vi; // expected-error{{volatile lvalue reference to type 'const volatile int' cannot bind to a temporary of type 'int'}} +} diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 9f80e7169bb1..a3ead79a8456 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -verify -std=c++11 -pedantic %s -Wno-comment +// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment namespace StaticAssertFoldTest { @@ -494,6 +494,27 @@ struct ArrayRVal { }; static_assert(ArrayRVal().elems[3].f() == 0, ""); +constexpr int selfref[2][2][2] = { + selfref[1][1][1] + 1, selfref[0][0][0] + 1, + selfref[1][0][1] + 1, selfref[0][1][0] + 1, + selfref[1][0][0] + 1, selfref[0][1][1] + 1 }; +static_assert(selfref[0][0][0] == 1, ""); +static_assert(selfref[0][0][1] == 2, ""); +static_assert(selfref[0][1][0] == 1, ""); +static_assert(selfref[0][1][1] == 2, ""); +static_assert(selfref[1][0][0] == 1, ""); +static_assert(selfref[1][0][1] == 3, ""); +static_assert(selfref[1][1][0] == 0, ""); +static_assert(selfref[1][1][1] == 0, ""); + +struct TrivialDefCtor { int n; }; +typedef TrivialDefCtor TDCArray[2][2]; +static_assert(TDCArray{}[1][1].n == 0, ""); + +struct NonAggregateTDC : TrivialDefCtor {}; +typedef NonAggregateTDC NATDCArray[2][2]; +static_assert(NATDCArray{}[1][1].n == 0, ""); + } namespace DependentValues { @@ -689,10 +710,16 @@ static_assert(&ok2 == pok2, ""); static_assert((Base2*)(Derived*)(Base*)pb1 == pok2, ""); static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, ""); -constexpr Base *nullB = 42 - 6 * 7; +constexpr Base *nullB = 42 - 6 * 7; // expected-warning {{expression which evaluates to zero treated as a null pointer constant of type 'Class::Base *const'}} static_assert((Bottom*)nullB == 0, ""); static_assert((Derived*)nullB == 0, ""); static_assert((void*)(Bottom*)nullB == (void*)(Derived*)nullB, ""); +Base * nullB2 = '\0'; // expected-warning {{expression which evaluates to zero treated as a null pointer constant of type 'Class::Base *'}} +Base * nullB3 = (0); +// We suppress the warning in unevaluated contexts to workaround some gtest +// behavior. Once this becomes an error this isn't a problem anymore. +static_assert(nullB == (1 - 1), ""); + namespace ConversionOperators { @@ -1213,6 +1240,17 @@ namespace RecursiveOpaqueExpr { constexpr int arr2[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 5 }; static_assert(LastNonzero(begin(arr2), end(arr2)) == 5, ""); + + constexpr int arr3[] = { + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static_assert(LastNonzero(begin(arr3), end(arr3)) == 2, ""); } namespace VLASizeof { @@ -1248,3 +1286,91 @@ namespace Vector { } constexpr auto v2 = g(4); } + +// PR12626, redux +namespace InvalidClasses { + void test0() { + struct X; // expected-note {{forward declaration}} + struct Y { bool b; X x; }; // expected-error {{field has incomplete type}} + Y y; + auto& b = y.b; + } +} + +// Constructors can be implicitly constexpr, even for a non-literal type. +namespace ImplicitConstexpr { + struct Q { Q() = default; Q(const Q&) = default; Q(Q&&) = default; ~Q(); }; // expected-note 3{{here}} + struct R { constexpr R() noexcept; constexpr R(const R&) noexcept; constexpr R(R&&) noexcept; ~R() noexcept; }; + struct S { R r; }; // expected-note 3{{here}} + struct T { T(const T&) noexcept; T(T &&) noexcept; ~T() noexcept; }; + struct U { T t; }; // expected-note 3{{here}} + static_assert(!__is_literal_type(Q), ""); + static_assert(!__is_literal_type(R), ""); + static_assert(!__is_literal_type(S), ""); + static_assert(!__is_literal_type(T), ""); + static_assert(!__is_literal_type(U), ""); + struct Test { + friend Q::Q() noexcept; // expected-error {{follows constexpr}} + friend Q::Q(Q&&) noexcept; // expected-error {{follows constexpr}} + friend Q::Q(const Q&) noexcept; // expected-error {{follows constexpr}} + friend S::S() noexcept; // expected-error {{follows constexpr}} + friend S::S(S&&) noexcept; // expected-error {{follows constexpr}} + friend S::S(const S&) noexcept; // expected-error {{follows constexpr}} + friend constexpr U::U() noexcept; // expected-error {{follows non-constexpr}} + friend constexpr U::U(U&&) noexcept; // expected-error {{follows non-constexpr}} + friend constexpr U::U(const U&) noexcept; // expected-error {{follows non-constexpr}} + }; +} + +// Indirectly test that an implicit lvalue to xvalue conversion performed for +// an NRVO move operation isn't implemented as CK_LValueToRValue. +namespace PR12826 { + struct Foo {}; + constexpr Foo id(Foo x) { return x; } + constexpr Foo res(id(Foo())); +} + +namespace PR13273 { + struct U { + int t; + U() = default; + }; + + struct S : U { + S() = default; + }; + + // S's default constructor isn't constexpr, because U's default constructor + // doesn't initialize 't', but it's trivial, so value-initialization doesn't + // actually call it. + static_assert(S{}.t == 0, ""); +} + +namespace PR12670 { + struct S { + constexpr S(int a0) : m(a0) {} + constexpr S() : m(6) {} + int m; + }; + constexpr S x[3] = { {4}, 5 }; + static_assert(x[0].m == 4, ""); + static_assert(x[1].m == 5, ""); + static_assert(x[2].m == 6, ""); +} + +// Indirectly test that an implicit lvalue-to-rvalue conversion is performed +// when a conditional operator has one argument of type void and where the other +// is a glvalue of class type. +namespace ConditionalLValToRVal { + struct A { + constexpr A(int a) : v(a) {} + int v; + }; + + constexpr A f(const A &a) { + return a.v == 0 ? throw a : a; + } + + constexpr A a(4); + static_assert(f(a).v == 4, ""); +} diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp index 23a4dda70838..ec50cb7d92fc 100644 --- a/test/SemaCXX/constant-expression.cpp +++ b/test/SemaCXX/constant-expression.cpp @@ -115,5 +115,12 @@ int array2[recurse2]; // expected-warning {{variable length array}} expected-war namespace FloatConvert { typedef int a[(int)42.3]; typedef int a[(int)42.997]; - typedef int b[(int)4e10]; // expected-warning {{variable length}} expected-error {{variable length}} + typedef int b[(long long)4e20]; // expected-warning {{variable length}} expected-error {{variable length}} expected-warning {{'long long' is an extension}} +} + +// PR12626 +namespace test3 { + struct X; // expected-note {{forward declaration of 'test3::X'}} + struct Y { bool b; X x; }; // expected-error {{field has incomplete type 'test3::X'}} + int f() { return Y().b; } } diff --git a/test/SemaCXX/constexpr-many-arguments.cpp b/test/SemaCXX/constexpr-many-arguments.cpp new file mode 100644 index 000000000000..3b5e974b3328 --- /dev/null +++ b/test/SemaCXX/constexpr-many-arguments.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s +// PR13197 + +struct type1 +{ + constexpr type1(int a0) : my_data{a0} {} + int my_data[1]; +}; + +struct type2 +{ + typedef type1 T; + constexpr type2(T a00, T a01, T a02, T a03, T a04, T a05, T a06, T a07, T a08, T a09, + T a10, T a11, T a12, T a13, T a14, T a15, T a16, T a17, T a18, T a19, + T a20, T a21, T a22) + : my_data{a00, a01, a02, a03, a04, a05, a06, a07, a08, a09, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, + a20, a21, a22} + {} + type1 my_data[23]; +}; + +struct type3 +{ + constexpr type3(type2 a0, type2 a1) : my_data{a0, a1} {} + type2 my_data[2]; +}; + +constexpr type3 g +{ + { + {0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, + {0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, + {0},{0},{0} + }, + { + {0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, + {0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, + {0},{0},{0} + } +}; + diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index e8b7f0b6760b..f503d01f360d 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -126,21 +126,24 @@ struct Q { // A silly class used to demonstrate field-is-uninitialized in constructors with // multiple params. +int IntParam(int i) { return 0; }; class TwoInOne { public: TwoInOne(TwoInOne a, TwoInOne b) {} }; class InitializeUsingSelfTest { bool A; char* B; int C; TwoInOne D; - InitializeUsingSelfTest(int E) + int E; + InitializeUsingSelfTest(int F) : A(A), // expected-warning {{field is uninitialized when used here}} B((((B)))), // expected-warning {{field is uninitialized when used here}} C(A && InitializeUsingSelfTest::C), // expected-warning {{field is uninitialized when used here}} D(D, // expected-warning {{field is uninitialized when used here}} - D) {} // expected-warning {{field is uninitialized when used here}} + D), // expected-warning {{field is uninitialized when used here}} + E(IntParam(E)) {} // expected-warning {{field is uninitialized when used here}} }; -int IntWrapper(int i) { return 0; }; +int IntWrapper(int &i) { return 0; }; class InitializeUsingSelfExceptions { int A; int B; @@ -229,13 +232,13 @@ namespace PR7402 { // <rdar://problem/8308215>: don't crash. // Lots of questionable recovery here; errors can change. namespace test3 { - class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 3 {{candidate}} expected-note {{passing argument}} + class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 2 {{candidate}} class B : public A { public: B(const String& s, int e=0) // expected-error {{unknown type name}} : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}} B(const B& e) - : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{no viable conversion}} expected-error {{does not name}} + : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{does not name}} expected-error {{no member named 'm_String' in 'test3::B'}} } }; } diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index a7a178244c80..6fca0503ba72 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -392,3 +392,14 @@ namespace PR8800 { A& a4 = (A&)c; } } + +namespace PR12712 { + struct A {}; + struct B { + operator A(); + operator A() const; + }; + struct C : B {}; + + A f(const C c) { return c; } +} diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index a64b18721a5f..ac235cc7feaf 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -65,19 +65,69 @@ void test3() { int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} int d; d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} - bool bl = NULL; // FIXME: this should warn but we currently suppress a bunch of conversion-to-bool warnings including this one + bool bl = NULL; // expected-warning {{implicit conversion of NULL constant to 'bool'}} char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}} unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}} short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}} + double dbl = NULL; // expected-warning {{implicit conversion of NULL constant to 'double'}} // Use FileCheck to ensure we don't get any unnecessary macro-expansion notes // (that don't appear as 'real' notes & can't be seen/tested by -verify) // CHECK-NOT: note: - // CHECK: note: expanded from macro 'FNULL' -#define FNULL NULL - int a2 = FNULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} - // CHECK-NOT: note: // CHECK: note: expanded from macro 'FINIT' #define FINIT int a3 = NULL; FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}} + + // we don't catch the case of #define FOO NULL ... int i = FOO; but that seems a bit narrow anyway + // and avoiding that helps us skip these cases: +#define NULL_COND(cond) ((cond) ? &a : NULL) + bool bl2 = NULL_COND(true); // don't warn on NULL conversion through the conditional operator across a macro boundary + if (NULL_COND(true)) + ; + while (NULL_COND(true)) + ; + for (; NULL_COND(true); ) + ; + do ; + while(NULL_COND(true)); + int *ip = NULL; + int (*fp)() = NULL; + struct foo { + int n; + void func(); + }; + int foo::*datamem = NULL; + int (foo::*funmem)() = NULL; +} + +namespace test4 { + // FIXME: We should warn for non-dependent args (only when the param type is also non-dependent) only once + // not once for the template + once for every instantiation + template<typename T> + void tmpl(char c = NULL, // expected-warning 4 {{implicit conversion of NULL constant to 'char'}} + T a = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} \ + expected-warning 2 {{implicit conversion of NULL constant to 'int'}} + T b = 1024) { // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1024 to 0}} + } + + template<typename T> + void tmpl2(T t = NULL) { + } + + void func() { + tmpl<char>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<char>' required here}} + tmpl<int>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<int>' required here}} + // FIXME: We should warn only once for each template instantiation - not once for each call + tmpl<int>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<int>' required here}} + tmpl2<int*>(); + } +} + +namespace test5 { + template<int I> + void func() { + bool b = I; + } + + template void func<3>(); } diff --git a/test/SemaCXX/crashes.cpp b/test/SemaCXX/crashes.cpp index b77248ef4104..d02704c87c74 100644 --- a/test/SemaCXX/crashes.cpp +++ b/test/SemaCXX/crashes.cpp @@ -104,3 +104,35 @@ namespace PR10270 { return; } } + +namespace rdar11806334 { + +class cc_YCbCr; + +class cc_rgb +{ + public: + cc_rgb( uint p ); // expected-error {{unknown type name}} + cc_rgb( cc_YCbCr v_in ); +}; + +class cc_hsl +{ + public: + cc_rgb rgb(); + cc_YCbCr YCbCr(); +}; + +class cc_YCbCr +{ + public: + cc_YCbCr( const cc_rgb v_in ); +}; + +cc_YCbCr cc_hsl::YCbCr() +{ + cc_YCbCr v_out = cc_YCbCr( rgb()); + return v_out; +} + +} diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index 32905956169b..641760e7e540 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -7,11 +7,14 @@ struct non_copiable { }; struct non_const_copy { - non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} - non_const_copy& operator = (non_const_copy&) & = default; // expected-note {{not viable}} - non_const_copy& operator = (non_const_copy&) && = default; // expected-note {{not viable}} + non_const_copy(non_const_copy&); + non_const_copy& operator = (non_const_copy&) &; + non_const_copy& operator = (non_const_copy&) &&; non_const_copy() = default; // expected-note {{not viable}} }; +non_const_copy::non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} +non_const_copy& non_const_copy::operator = (non_const_copy&) & = default; // expected-note {{not viable}} +non_const_copy& non_const_copy::operator = (non_const_copy&) && = default; // expected-note {{not viable}} void fn1 () { non_copiable nc; @@ -21,7 +24,8 @@ void fn1 () { non_const_copy ncc; non_const_copy ncc2 = ncc; ncc = ncc2; - const non_const_copy cncc; + const non_const_copy cncc{}; + const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' requires a user-provided default constructor}} non_const_copy ncc3 = cncc; // expected-error {{no matching}} ncc = cncc; // expected-error {{no viable overloaded}} }; @@ -32,9 +36,9 @@ struct non_const_derived : non_const_copy { }; 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(volatile bad_decls&) = default; // expected-error {{may not be volatile}} expected-error {{must be defaulted outside the class}} + bad_decls&& operator = (bad_decls) = default; // expected-error {{lvalue reference}} expected-error {{must return 'bad_decls &'}} + bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} expected-error {{must be defaulted outside the class}} bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const', 'constexpr' or 'volatile' qualifiers}} }; @@ -66,10 +70,9 @@ struct except_spec_d_mismatch : except_spec_a, except_spec_b { }; struct except_spec_d_match : except_spec_a, except_spec_b { except_spec_d_match() throw(A, B) = default; -}; +}; // gcc-compatibility: allow attributes on default definitions // (but not normal definitions) struct S { S(); }; S::S() __attribute((pure)) = default; - diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 2e4107c13e2d..ce7ee672ea19 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -6,26 +6,26 @@ struct foo { foo() = default; foo(const foo&) = default; - foo(foo&) = default; + foo(foo&&) = default; foo& operator = (const foo&) = default; - foo& operator = (foo&) = default; + foo& operator = (foo&&) = default; ~foo() = default; }; struct bar { bar(); bar(const bar&); - bar(bar&); + bar(bar&&); bar& operator = (const bar&); - bar& operator = (bar&); + bar& operator = (bar&&); ~bar(); }; bar::bar() = default; bar::bar(const bar&) = default; -bar::bar(bar&) = default; +bar::bar(bar&&) = default; bar& bar::operator = (const bar&) = default; -bar& bar::operator = (bar&) = default; +bar& bar::operator = (bar&&) = default; bar::~bar() = default; static_assert(__is_trivial(foo), "foo should be trivial"); @@ -51,3 +51,101 @@ template<typename T> struct S : T { struct lit { constexpr lit() {} }; S<lit> s_lit; // ok S<bar> s_bar; // ok + +struct Friends { + friend S<bar>::S(); + friend S<bar>::S(const S&); + friend S<bar>::S(S&&); +}; + +namespace DefaultedFnExceptionSpec { + // DR1330: The exception-specification of an implicitly-declared special + // member function is evaluated as needed. + template<typename T> T &&declval(); + template<typename T> struct pair { + pair(const pair&) noexcept(noexcept(T(declval<T>()))); + }; + + struct Y; + struct X { X(); X(const Y&); }; + struct Y { pair<X> p; }; + + template<typename T> + struct A { + pair<T> p; + }; + struct B { + B(); + B(const A<B>&); + }; + + // Don't crash here. + void f() { + X x = X(); + (void)noexcept(B(declval<B>())); + } + + template<typename T> + struct Error { + // FIXME: Type canonicalization causes all the errors to point at the first + // declaration which has the type 'void () noexcept (T::error)'. We should + // get one error for 'Error<int>::Error()' and one for 'Error<int>::~Error()'. + void f() noexcept(T::error); // expected-error 2{{has no members}} + + Error() noexcept(T::error); + Error(const Error&) noexcept(T::error); + Error(Error&&) noexcept(T::error); + Error &operator=(const Error&) noexcept(T::error); + Error &operator=(Error&&) noexcept(T::error); + ~Error() noexcept(T::error); + }; + + struct DelayImplicit { + Error<int> e; + }; + + // Don't instantiate the exception specification here. + void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit()))); + void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>())); + void test3(decltype(DelayImplicit(declval<const DelayImplicit>()))); + + // Any odr-use causes the exception specification to be evaluated. + struct OdrUse { // \ + expected-note {{instantiation of exception specification for 'Error'}} \ + expected-note {{instantiation of exception specification for '~Error'}} + Error<int> e; + }; + OdrUse use; // expected-note {{implicit default constructor for 'DefaultedFnExceptionSpec::OdrUse' first required here}} +} + +namespace PR13527 { + struct X { + X() = delete; // expected-note {{here}} + X(const X&) = delete; // expected-note {{here}} + X(X&&) = delete; // expected-note {{here}} + X &operator=(const X&) = delete; // expected-note {{here}} + X &operator=(X&&) = delete; // expected-note {{here}} + ~X() = delete; // expected-note {{here}} + }; + X::X() = default; // expected-error {{redefinition}} + X::X(const X&) = default; // expected-error {{redefinition}} + X::X(X&&) = default; // expected-error {{redefinition}} + X &X::operator=(const X&) = default; // expected-error {{redefinition}} + X &X::operator=(X&&) = default; // expected-error {{redefinition}} + X::~X() = default; // expected-error {{redefinition}} + + struct Y { + Y() = default; + Y(const Y&) = default; + Y(Y&&) = default; + Y &operator=(const Y&) = default; + Y &operator=(Y&&) = default; + ~Y() = default; + }; + Y::Y() = default; // expected-error {{definition of explicitly defaulted}} + Y::Y(const Y&) = default; // expected-error {{definition of explicitly defaulted}} + Y::Y(Y&&) = default; // expected-error {{definition of explicitly defaulted}} + Y &Y::operator=(const Y&) = default; // expected-error {{definition of explicitly defaulted}} + Y &Y::operator=(Y&&) = default; // expected-error {{definition of explicitly defaulted}} + Y::~Y() = default; // expected-error {{definition of explicitly defaulted}} +} diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp index 801a82f57065..c83058a5e196 100644 --- a/test/SemaCXX/cxx0x-initializer-aggregates.cpp +++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp @@ -87,3 +87,32 @@ namespace array_explicit_conversion { (void)test4{{{1}}}; // expected-note {{in instantiation of template class 'array_explicit_conversion::A<-1>' requested here}} } } + +namespace sub_constructor { + struct DefaultConstructor { // expected-note 2 {{not viable}} + DefaultConstructor(); // expected-note {{not viable}} + int x; + }; + struct NoDefaultConstructor1 { // expected-note 2 {{not viable}} + NoDefaultConstructor1(int); // expected-note {{not viable}} + int x; + }; + struct NoDefaultConstructor2 { // expected-note 4 {{not viable}} + NoDefaultConstructor2(int,int); // expected-note 2 {{not viable}} + int x; + }; + + struct Aggr { + DefaultConstructor a; + NoDefaultConstructor1 b; + NoDefaultConstructor2 c; + }; + + Aggr ok1 { {}, {0} , {0,0} }; + Aggr ok2 = { {}, {0} , {0,0} }; + Aggr too_many { {0} , {0} , {0,0} }; // expected-error {{no matching constructor for initialization}} + Aggr too_few { {} , {0} , {0} }; // expected-error {{no matching constructor for initialization}} + Aggr invalid { {} , {&ok1} , {0,0} }; // expected-error {{no matching constructor for initialization}} + NoDefaultConstructor2 array_ok[] = { {0,0} , {0,1} }; + NoDefaultConstructor2 array_error[] = { {0,0} , {0} }; // expected-error {{no matching constructor for initialization}} +}
\ No newline at end of file diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp index 09aca24b704b..223e140ffc02 100644 --- a/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -279,5 +279,28 @@ namespace PR12498 { { c->foo({ nullptr, 1 }); // expected-error{{initialization of incomplete type 'const PR12498::ArrayRef'}} } +} + +namespace explicit_default { + struct A { + explicit A(); // expected-note{{here}} + }; + A a {}; // ok + // This is copy-list-initialization, and we choose an explicit constructor + // (even though we do so via value-initialization), so the initialization is + // ill-formed. + A b = {}; // expected-error{{chosen constructor is explicit}} +} +namespace init_list_default { + struct A { + A(std::initializer_list<int>); + }; + A a {}; // calls initializer list constructor + + struct B { + B(); + B(std::initializer_list<int>) = delete; + }; + B b {}; // calls default constructor } diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index 7384309f97da..f11e19ae6f2c 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -175,3 +175,15 @@ namespace PR12436 { X x({}, 17); } + +namespace rdar11948732 { + template<typename T> struct X {}; + + struct XCtorInit { + XCtorInit(std::initializer_list<X<int>>); + }; + + void f(X<int> &xi) { + XCtorInit xc = { xi, xi }; + } +} diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp index 00532d5ac073..c07f64e614d2 100644 --- a/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -9,7 +9,7 @@ #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}} +VA_MACRO(,x) // expected-warning {{empty macro arguments are incompatible with C++98}} ; // expected-warning {{extra ';' outside of a function is incompatible with C++98}} diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 82a9dc8042c4..37341f885619 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -1,7 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -namespace std { struct type_info; } +namespace std { + struct type_info; + using size_t = decltype(sizeof(0)); // expected-warning {{decltype}} expected-warning {{alias}} + template<typename T> struct initializer_list { + initializer_list(T*, size_t); + T *p; + size_t n; + }; +} template<typename ...T> // expected-warning {{variadic templates are incompatible with C++98}} class Variadic1 {}; @@ -39,6 +47,14 @@ void Lambda() { []{}(); // expected-warning {{lambda expressions are incompatible with C++98}} } +struct Ctor { + Ctor(int, char); + Ctor(double, long); +}; +struct InitListCtor { + InitListCtor(std::initializer_list<bool>); +}; + int InitList(int i = {}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} \ // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ @@ -48,6 +64,14 @@ int InitList(int i = {}) { // expected-warning {{generalized initializer lists a int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} S<int> s = {}; // ok, aggregate s = {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} + std::initializer_list<int> xs = { 1, 2, 3 }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} + auto ys = { 1, 2, 3 }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} \ + // expected-warning {{'auto' type specifier is incompatible with C++98}} + Ctor c1 = { 1, 2 }; // expected-warning {{constructor call from initializer list is incompatible with C++98}} + Ctor c2 = { 3.0, 4l }; // expected-warning {{constructor call from initializer list is incompatible with C++98}} + InitListCtor ilc = { true, false }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} + const int &r = { 0 }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} + struct { int a; const int &r; } rr = { 0, {{0}} }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} } struct DelayedDefaultArgumentParseInitList { @@ -303,3 +327,38 @@ namespace NonTypeTemplateArgs { S<const int&, k> s1; // expected-warning {{non-type template argument referring to object 'k' with internal linkage is incompatible with C++98}} S<void(&)(), f> s2; // expected-warning {{non-type template argument referring to function 'f' with internal linkage is incompatible with C++98}} } + +namespace NullPointerTemplateArg { + struct A {}; + template<int*> struct X {}; + template<int A::*> struct Y {}; + X<(int*)0> x; // expected-warning {{use of null pointer as non-type template argument is incompatible with C++98}} + Y<(int A::*)0> y; // expected-warning {{use of null pointer as non-type template argument is incompatible with C++98}} +} + +namespace PR13480 { + struct basic_iterator { + basic_iterator(const basic_iterator &it) {} + basic_iterator(basic_iterator &it) {} // expected-note {{because type 'PR13480::basic_iterator' has a user-declared copy constructor}} + }; + + union test { + basic_iterator it; // expected-warning {{union member 'it' with a non-trivial copy constructor is incompatible with C++98}} + }; +} + +namespace AssignOpUnion { + struct a { + void operator=(const a &it) {} + void operator=(a &it) {} // expected-note {{because type 'AssignOpUnion::a' has a user-declared copy assignment operator}} + }; + + struct b { + void operator=(const b &it) {} // expected-note {{because type 'AssignOpUnion::b' has a user-declared copy assignment operator}} + }; + + union test1 { + a x; // expected-warning {{union member 'x' with a non-trivial copy assignment operator is incompatible with C++98}} + b y; // expected-warning {{union member 'y' with a non-trivial copy assignment operator is incompatible with C++98}} + }; +} diff --git a/test/SemaCXX/dcl_ambig_res.cpp b/test/SemaCXX/dcl_ambig_res.cpp index fa71b11ba160..08867c0ea2f5 100644 --- a/test/SemaCXX/dcl_ambig_res.cpp +++ b/test/SemaCXX/dcl_ambig_res.cpp @@ -10,9 +10,9 @@ int returns_an_int(); void foo(double a) { - S w(int(a)); // expected-warning{{disambiguated}} + S w(int(a)); // expected-warning{{disambiguated as a function declaration}} expected-note{{add a pair of parentheses}} w(17); - S x1(int()); // expected-warning{{disambiguated}} + S x1(int()); // expected-warning{{disambiguated as a function declaration}} expected-note{{add a pair of parentheses}} x1(&returns_an_int); S y((int)a); y.bar(); @@ -69,7 +69,7 @@ struct S5 { static bool const value = false; }; int foo8() { - int v(int(S5::value)); // expected-warning{{disambiguated}} expected-error{{parameter declarator cannot be qualified}} + int v(int(S5::value)); // expected-warning{{disambiguated as a function declaration}} expected-note{{add a pair of parentheses}} expected-error{{parameter declarator cannot be qualified}} } template<typename T> diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp index bd3de9eb7e19..8c5e654fca2e 100644 --- a/test/SemaCXX/dcl_init_aggr.cpp +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -15,7 +15,7 @@ struct NonAggregate { }; NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{non-aggregate type 'NonAggregate' cannot be initialized with an initializer list}} -NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'NonAggregate' with an initializer list}} +NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{non-aggregate type 'NonAggregate' cannot be initialized with an initializer list}} // C++ [dcl.init.aggr]p3 diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 6f4d08cc686c..0980c40cbfd5 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -22,10 +22,10 @@ void f() { (int())1; // expected-error {{C-style cast from 'int' to 'int ()' is not allowed}} // Declarations. - int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}} - T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-note {{previous definition is here}} - typedef T(*td)(int(p)); - extern T(*tp)(int(p)); + int fd(T(a)); // expected-warning {{disambiguated as a function declaration}} expected-note{{add a pair of parentheses}} + T(*d)(int(p)); // expected-note {{previous}} + typedef T td(int(p)); + extern T tp(int(p)); T d3(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} T d3v(void); typedef T d3t(); @@ -49,6 +49,7 @@ struct RAII { }; void func(); +void func2(short); namespace N { struct S; @@ -59,6 +60,10 @@ namespace N { S s(); // expected-warning {{function declaration}} } + void nonEmptyParens() { + int f = 0, // g = 0; expected-note {{change this ',' to a ';' to call 'func2'}} + func2(short(f)); // expected-warning {{function declaration}} expected-note {{add a pair of parentheses}} + } } class C { }; @@ -70,3 +75,23 @@ void foo() { fn(1); // expected-error {{no matching function}} fn(g); // OK } + +namespace PR11874 { +void foo(); // expected-note 3 {{class 'foo' is hidden by a non-type declaration of 'foo' here}} +class foo {}; +class bar { + bar() { + const foo* f1 = 0; // expected-error {{must use 'class' tag to refer to type 'foo' in this scope}} + foo* f2 = 0; // expected-error {{must use 'class' tag to refer to type 'foo' in this scope}} + foo f3; // expected-error {{must use 'class' tag to refer to type 'foo' in this scope}} + } +}; + +int baz; // expected-note 2 {{class 'baz' is hidden by a non-type declaration of 'baz' here}} +class baz {}; +void fizbin() { + const baz* b1 = 0; // expected-error {{must use 'class' tag to refer to type 'baz' in this scope}} + baz* b2; // expected-error {{use of undeclared identifier 'b2'}} + baz b3; // expected-error {{must use 'class' tag to refer to type 'baz' in this scope}} +} +} diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp index ae6ef9791c2a..c8c197e153d4 100644 --- a/test/SemaCXX/default1.cpp +++ b/test/SemaCXX/default1.cpp @@ -47,6 +47,13 @@ int i () { void j (int f = 4); { void j (int f); // expected-note{{'j' declared here}} - j(); // expected-error{{too few arguments to function call, expected 1, have 0}} + j(); // expected-error{{too few arguments to function call, single argument 'f' was not specified}} + } +} + +int i2() { + void j(int f = 4); // expected-note{{'j' declared here}} + { + j(2, 3); // expected-error{{too many arguments to function call, expected at most single argument 'f', have 2}} } } diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index d13fd0eb7b4f..e78e7edc7199 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -55,3 +55,13 @@ struct Z : virtual DelDtor { ~Z() {} // expected-error {{attempt to use a deleted function}} }; DelDtor dd; // expected-error {{attempt to use a deleted function}} + +template<typename> void test2() = delete; +template void test2<int>(); + +template<typename> void test3() = delete; +template<typename> void test3(); +template void test3<int>(); + +void test4() {} // expected-note {{previous definition is here}} +void test4() = delete; // expected-error {{redefinition of 'test4'}} diff --git a/test/SemaCXX/deleted-operator.cpp b/test/SemaCXX/deleted-operator.cpp index 0e0282ad12cc..9f53e71d456c 100644 --- a/test/SemaCXX/deleted-operator.cpp +++ b/test/SemaCXX/deleted-operator.cpp @@ -8,8 +8,8 @@ struct PR10757 { 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}} + if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 8 {{built-in candidate}} + if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 121 {{built-in candidate}} } struct DelOpDel { diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp index 760079f3b0bc..1b1770a89f85 100644 --- a/test/SemaCXX/elaborated-type-specifier.cpp +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -19,7 +19,7 @@ bool test_elab(S1 *s1, struct S2 *s2, struct S3 *s3) { namespace NS { class X { public: - void test_elab2(struct S4 *s4); + void test_elab2(struct S4 *s4); // expected-note{{'NS::S4' declared here}} }; void X::test_elab2(S4 *s4) { } // expected-note{{passing argument to parameter 's4' here}} @@ -35,8 +35,7 @@ namespace NS { } void test_S5_scope() { - S4 *s4; // expected-error{{use of undeclared identifier 'S4'}} \ - // expected-error{{use of undeclared identifier 's4'}} + S4 *s4; // expected-error{{unknown type name 'S4'; did you mean 'NS::S4'?}} } int test_funcparam_scope(struct S5 * s5) { @@ -44,5 +43,3 @@ int test_funcparam_scope(struct S5 * s5) { if (s5 == s5_2) return 1; // expected-error {{comparison of distinct pointer types ('struct S5 *' and 'struct S5 *')}} return 0; } - - diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index ebe924535850..a1f911d79d39 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -245,3 +245,10 @@ namespace test10 { int m = g<int>(); int n = g<short>(); // expected-note {{here}} } + +namespace pr13128 { + // This should compile cleanly + class C { + enum class E { C }; + }; +} diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp index 355833e693fa..2635fb8d176a 100644 --- a/test/SemaCXX/expressions.cpp +++ b/test/SemaCXX/expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s void choice(int); int choice(bool); diff --git a/test/SemaCXX/format-strings-0x.cpp b/test/SemaCXX/format-strings-0x.cpp index e7c5904c66e3..7b3aef1ee5da 100644 --- a/test/SemaCXX/format-strings-0x.cpp +++ b/test/SemaCXX/format-strings-0x.cpp @@ -12,4 +12,16 @@ void f(char **sp, float *fp) { scanf("%afoobar", fp); printf(nullptr); printf(*sp); // expected-warning {{not a string literal}} + + // PR13099 + printf( + R"foobar(%)foobar" + R"bazquux(d)bazquux" // expected-warning {{more '%' conversions than data arguments}} + R"xyzzy()xyzzy"); + + printf(u8"this is %d test", 0); // ok + printf(u8R"foo( + \u1234\U0010fffe + %d)foo" // expected-warning {{more '%' conversions than data arguments}} + ); } diff --git a/test/SemaCXX/function-extern-c.cpp b/test/SemaCXX/function-extern-c.cpp index f20cd38a3cb0..16dbbb26fc66 100644 --- a/test/SemaCXX/function-extern-c.cpp +++ b/test/SemaCXX/function-extern-c.cpp @@ -36,3 +36,5 @@ extern "C" void f7( U u ); extern "C" double f8(void); extern "C" long long f11( void ); extern "C" A *f10( void ); + +extern "C" struct mypodstruct f12(); // expected-warning {{'f12' has C-linkage specified, but returns incomplete type 'struct mypodstruct' which could be incompatible with C}} diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp index 0eb109d2633b..b9d1f23af402 100644 --- a/test/SemaCXX/function-redecl.cpp +++ b/test/SemaCXX/function-redecl.cpp @@ -76,12 +76,9 @@ class Crash { void GetCart(int count) const; }; // This out-of-line definition was fine... -void Crash::cart(int count) const {} // expected-error {{out-of-line definition of 'cart' does not match any declaration in 'Crash'}} \ - // expected-note {{'cart' declared here}} \ - // expected-note {{previous definition is here}} +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'; did you mean 'cart'?}} \ - // expected-error {{redefinition of 'cart'}} +void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'}} class TestConst { public: @@ -98,3 +95,24 @@ void TestConst::setit(int) const { // expected-error {{out-of-line definition of 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'}} + +// Ensure we correct the redecl of Foo::isGood to Bar::Foo::isGood and not +// Foo::IsGood even though Foo::IsGood is technically a closer match since it +// already has a body. Also make sure Foo::beEvil is corrected to Foo::BeEvil +// since it is a closer match than Bar::Foo::beEvil and neither have a body. +namespace redecl_typo { +namespace Foo { + bool IsGood() { return false; } + void BeEvil(); // expected-note {{'BeEvil' declared here}} +} +namespace Bar { + namespace Foo { + bool isGood(); // expected-note {{'Bar::Foo::isGood' declared here}} + void beEvil(); + } +} +bool Foo::isGood() { // expected-error {{out-of-line definition of 'isGood' does not match any declaration in namespace 'redecl_typo::Foo'; did you mean 'Bar::Foo::isGood'?}} + return true; +} +void Foo::beEvil() {} // expected-error {{out-of-line definition of 'beEvil' does not match any declaration in namespace 'redecl_typo::Foo'; did you mean 'BeEvil'?}} +} diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp index 25316f8d51ee..b29cff5c5d12 100644 --- a/test/SemaCXX/implicit-exception-spec.cpp +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -17,7 +17,7 @@ namespace InClassInitializers { // is false. bool ThrowSomething() noexcept(false); struct ConstExpr { - bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{exception specification is not available until end of class definition}} + bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{cannot be used by non-static data member initializer}} }; // We can use it now. bool w = noexcept(ConstExpr()); @@ -25,18 +25,27 @@ namespace InClassInitializers { // Much more obviously broken: we can't parse the initializer without already // knowing whether it produces a noexcept expression. struct TemplateArg { - int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{exception specification is not available until end of class definition}} + int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{cannot be used by non-static data member initializer}} }; bool x = noexcept(TemplateArg()); // And within a nested class. + // FIXME: The diagnostic location is terrible here. struct Nested { struct Inner { - int n = ExceptionIf<noexcept(Nested())>::f(); // expected-error {{exception specification is not available until end of class definition}} - } inner; + int n = ExceptionIf<noexcept(Nested())>::f(); + } inner; // expected-error {{cannot be used by non-static data member initializer}} }; bool y = noexcept(Nested()); bool z = noexcept(Nested::Inner()); + + struct Nested2 { + struct Inner; + int n = Inner().n; // expected-error {{cannot be used by non-static data member initializer}} + struct Inner { + int n = ExceptionIf<noexcept(Nested())>::f(); + } inner; + }; } namespace ExceptionSpecification { diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp index 287d9af13094..87da79a27c0c 100644 --- a/test/SemaCXX/invalid-member-expr.cpp +++ b/test/SemaCXX/invalid-member-expr.cpp @@ -37,3 +37,34 @@ namespace test3 { string::iterator i = s.foo(); // expected-error {{no member named 'foo'}} } } + + +// Make sure we don't crash. +namespace rdar11293995 { + +struct Length { + explicit Length(PassRefPtr<CalculationValue>); // expected-error {{unknown type name}} \ + expected-error {{expected ')'}} \ + expected-note {{to match this '('}} +}; + +struct LengthSize { + Length m_width; + Length m_height; +}; + +enum EFillSizeType { Contain, Cover, SizeLength, SizeNone }; + +struct FillSize { + EFillSizeType type; + LengthSize size; +}; + +class FillLayer { +public: + void setSize(FillSize f) { m_sizeType = f.type;} +private: + unsigned m_sizeType : 2; +}; + +} diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index e91dee92edb1..0fd634502bc9 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -17,74 +17,71 @@ namespace ExplicitCapture { [this](){(void)Member;}; [this]{[this]{};}; []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}} - []{Overload(3);}; - []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}} + []{Overload(3);}; + []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}} []{(void)typeid(Overload());}; - []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}} + []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}} } }; void f() { - [this] () {}; // expected-error {{'this' cannot be captured in this context}} + [this] () {}; // expected-error {{'this' cannot be captured in this context}} } } namespace ReturnDeduction { void test() { - [](){ return 1; }; - [](){ return 1; }; - [](){ return ({return 1; 1;}); }; - [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} \ - // expected-warning{{omitted result type}} - []()->int{ return 'c'; return 1; }; + [](){ return 1; }; + [](){ return 1; }; + [](){ return ({return 1; 1;}); }; + [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} + []()->int{ return 'c'; return 1; }; [](){ return 'c'; return 1; }; // expected-error {{must match previous return type}} - []() { return; return (void)0; }; - [](){ return 1; return 1; }; // expected-warning{{omitted result type}} + []() { return; return (void)0; }; + [](){ return 1; return 1; }; } } namespace ImplicitCapture { void test() { int a = 0; // expected-note 5 {{declared}} - []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} - [&]() { return a; }; - [=]() { return a; }; - [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}} + []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} + [&]() { return a; }; + [=]() { return a; }; + [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}} [=]() { return [&]() { return a; }; }; - []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} - []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} - []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} - [=]() { return [&a] { return a; }; }; // + []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} + [=]() { return [&a] { return a; }; }; // const int b = 2; - []() { return b; }; + []() { return b; }; union { // expected-note {{declared}} int c; float d; }; d = 3; - [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} + [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} __block int e; // expected-note 3 {{declared}} - [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}} - [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}} + [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}} + [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}} int f[10]; // expected-note {{declared}} - [&]() { return f[2]; }; + [&]() { return f[2]; }; (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \ // expected-note{{lambda expression begins here}} struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}} G g; - [=]() { const G* gg = &g; return gg->a; }; // expected-warning{{omitted result type}} - [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}} \ - // expected-warning{{omitted result type}} - (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}} \ - // expected-warning{{omitted result type}} + [=]() { const G* gg = &g; return gg->a; }; + [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}} + (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}} const int h = a; // expected-note {{declared}} - []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} // The exemption for variables which can appear in constant expressions // applies only to objects (and not to references). @@ -120,16 +117,16 @@ namespace NullPtr { const int m = 0; [=] { - int &k = f(m); // a null pointer constant + int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} } (); [=] () -> bool { - int &k = f(m); // a null pointer constant + int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} return &m == 0; } (); [m] { - int &k = f(m); // a null pointer constant + int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} } (); } } @@ -148,3 +145,79 @@ namespace ModifyingCapture { }; } } + +namespace VariadicPackExpansion { + template<typename T, typename U> using Fst = T; + template<typename...Ts> bool g(Fst<bool, Ts> ...bools); + template<typename...Ts> bool f(Ts &&...ts) { + return g<Ts...>([&ts] { + if (!ts) + return false; + --ts; + return true; + } () ...); + } + void h() { + int a = 5, b = 2, c = 3; + while (f(a, b, c)) { + } + } + + struct sink { + template<typename...Ts> sink(Ts &&...) {} + }; + + template<typename...Ts> void local_class() { + sink { + [] (Ts t) { + struct S : Ts { + void f(Ts t) { + Ts &that = *this; + that = t; + } + Ts g() { return *this; }; + }; + S s; + s.f(t); + return s; + } (Ts()).g() ... + }; + }; + struct X {}; struct Y {}; + template void local_class<X, Y>(); + + template<typename...Ts> void nested(Ts ...ts) { + f( + // Each expansion of this lambda implicitly captures all of 'ts', because + // the inner lambda also expands 'ts'. + [&] { + return ts + [&] { return f(ts...); } (); + } () ... + ); + } + template void nested(int, int, int); + + template<typename...Ts> void nested2(Ts ...ts) { // expected-note 2{{here}} + // Capture all 'ts', use only one. + f([&ts...] { return ts; } ()...); + // Capture each 'ts', use it. + f([&ts] { return ts; } ()...); + // Capture all 'ts', use all of them. + f([&ts...] { return (int)f(ts...); } ()); + // Capture each 'ts', use all of them. Ill-formed. In more detail: + // + // We instantiate two lambdas here; the first captures ts$0, the second + // captures ts$1. Both of them reference both ts parameters, so both are + // ill-formed because ts can't be implicitly captured. + // + // FIXME: This diagnostic does not explain what's happening. We should + // specify which 'ts' we're referring to in its diagnostic name. We should + // also say which slice of the pack expansion is being performed in the + // instantiation backtrace. + f([&ts] { return (int)f(ts...); } ()...); // \ + // expected-error 2{{'ts' cannot be implicitly captured}} \ + // expected-note 2{{lambda expression begins here}} + } + template void nested2(int); // ok + template void nested2(int, int); // expected-note {{in instantiation of}} +} diff --git a/test/SemaCXX/literal-operators.cpp b/test/SemaCXX/literal-operators.cpp index 7f68cd393cad..f4c5c35a2bcb 100644 --- a/test/SemaCXX/literal-operators.cpp +++ b/test/SemaCXX/literal-operators.cpp @@ -41,3 +41,4 @@ void operator "" _cv_good (volatile const char *, const size_t); // expected-err template <char...> void operator "" _good (); // FIXME: Test some invalid decls that might crop up. +template <typename...> void operator "" _invalid(); // expected-error {{parameter declaration for literal operator 'operator "" _invalid' is not valid}} diff --git a/test/SemaCXX/long-virtual-inheritance-chain.cpp b/test/SemaCXX/long-virtual-inheritance-chain.cpp new file mode 100644 index 000000000000..85995971d240 --- /dev/null +++ b/test/SemaCXX/long-virtual-inheritance-chain.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +class test0 { virtual void f(); }; +class test1 : virtual test0 { virtual void f(); }; +class test2 : virtual test1 { virtual void f(); }; +class test3 : virtual test2 { virtual void f(); }; +class test4 : virtual test3 { virtual void f(); }; +class test5 : virtual test4 { virtual void f(); }; +class test6 : virtual test5 { virtual void f(); }; +class test7 : virtual test6 { virtual void f(); }; +class test8 : virtual test7 { virtual void f(); }; +class test9 : virtual test8 { virtual void f(); }; +class test10 : virtual test9 { virtual void f(); }; +class test11 : virtual test10 { virtual void f(); }; +class test12 : virtual test11 { virtual void f(); }; +class test13 : virtual test12 { virtual void f(); }; +class test14 : virtual test13 { virtual void f(); }; +class test15 : virtual test14 { virtual void f(); }; +class test16 : virtual test15 { virtual void f(); }; +class test17 : virtual test16 { virtual void f(); }; +class test18 : virtual test17 { virtual void f(); }; +class test19 : virtual test18 { virtual void f(); }; +class test20 : virtual test19 { virtual void f(); }; +class test21 : virtual test20 { virtual void f(); }; +class test22 : virtual test21 { virtual void f(); }; +class test23 : virtual test22 { virtual void f(); }; +class test24 : virtual test23 { virtual void f(); }; +class test25 : virtual test24 { virtual void f(); }; +class test26 : virtual test25 { virtual void f(); }; +class test27 : virtual test26 { virtual void f(); }; +class test28 : virtual test27 { virtual void f(); }; +class test29 : virtual test28 { virtual void f(); }; +class test30 : virtual test29 { virtual void f(); }; +class test31 : virtual test30 { virtual void f(); }; +class test32 : virtual test31 { virtual void f(); }; +class test33 : virtual test32 { virtual void f(); }; +class test34 : virtual test33 { virtual void f(); }; +class test35 : virtual test34 { virtual void f(); }; +class test36 : virtual test35 { virtual void f(); }; +class test37 : virtual test36 { virtual void f(); }; +class test38 : virtual test37 { virtual void f(); }; +class test39 : virtual test38 { virtual void f(); }; +class test40 : virtual test39 { virtual void f(); }; +class test41 : virtual test40 { virtual void f(); }; +class test42 : virtual test41 { virtual void f(); }; +class test43 : virtual test42 { virtual void f(); }; +class test44 : virtual test43 { virtual void f(); }; +class test45 : virtual test44 { virtual void f(); }; +class test46 : virtual test45 { virtual void f(); }; +class test47 : virtual test46 { virtual void f(); }; +class test48 : virtual test47 { virtual void f(); }; +class test49 : virtual test48 { virtual void f(); }; +class test50 : virtual test49 { virtual void f(); }; diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index dbddd1c2e3e1..763f9c754c1e 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -157,3 +157,13 @@ namespace FuncInMemberExpr { Vec fun3(int x = 0); int test3() { return fun3.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} } + +namespace DotForSemiTypo { +void f(int i) { + // If the programmer typo'd '.' for ';', make sure we point at the '.' rather + // than the "field name" (whatever the first token on the next line happens to + // be). + int j = i. // expected-error {{member reference base type 'int' is not a structure or union}} + j = 0; +} +} diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index c93c85bbf89a..a13941fce5d8 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -14,7 +14,7 @@ public: bool b(); int k; struct Recurse { - int &n = b() ? Recurse().n : k; // ok + int &n = b() ? Recurse().n : k; // expected-error {{defaulted default constructor of 'Recurse' cannot be used by non-static data member initializer which appears before end of class definition}} }; struct UnknownBound { @@ -28,7 +28,7 @@ template<> struct T<2> { template<int C, int D> using B = int; }; const int C = 0, D = 0; struct S { int as[] = { decltype(x)::B<C, D>(0) }; // expected-error {{array bound cannot be deduced from an in-class initializer}} - T<sizeof(as) / sizeof(int)> x; // expected-error {{requires a type specifier}} + T<sizeof(as) / sizeof(int)> x; // test that we handle invalid array bound deductions without crashing when the declarator name is itself invalid operator int[](){}; // expected-error {{'operator int' cannot be the name of a variable or data member}} \ // expected-error {{array bound cannot be deduced from an in-class initializer}} diff --git a/test/SemaCXX/member-operator-expr.cpp b/test/SemaCXX/member-operator-expr.cpp index ae5f8bb0ddb6..c98ef7399709 100644 --- a/test/SemaCXX/member-operator-expr.cpp +++ b/test/SemaCXX/member-operator-expr.cpp @@ -27,3 +27,8 @@ void test2() { x->operator float(); // expected-error{{no member named 'operator float'}} x->operator; // expected-error{{expected a type}} } + +namespace pr13157 { + class A { public: void operator()(int x, int y = 2, ...) {} }; + void f() { A()(1); } +}
\ No newline at end of file diff --git a/test/SemaCXX/microsoft-cxx0x.cpp b/test/SemaCXX/microsoft-cxx0x.cpp index 3b9bbefc0cd6..79bd7c39e5a5 100644 --- a/test/SemaCXX/microsoft-cxx0x.cpp +++ b/test/SemaCXX/microsoft-cxx0x.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++11-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11 +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++11-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11 -fms-compatibility -DMS_COMPAT struct A { @@ -6,3 +7,16 @@ struct A { }; int b = 3; A var = { b }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + +namespace PR13433 { + struct S; + S make(); + + template<typename F> auto x(F f) -> decltype(f(make())); +#ifndef MS_COMPAT +// expected-error@-2{{calling 'make' with incomplete return type 'PR13433::S'}} +// expected-note@-5{{'make' declared here}} +// expected-note@-7{{forward declaration of 'PR13433::S'}} +#endif +} diff --git a/test/SemaCXX/neon-vector-types.cpp b/test/SemaCXX/neon-vector-types.cpp index aa82b11e8cd7..336fcd4f18d6 100644 --- a/test/SemaCXX/neon-vector-types.cpp +++ b/test/SemaCXX/neon-vector-types.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify "-triple" "thumbv7-apple-ios3.0.0" %s // rdar://9208404 typedef int MP4Err; @@ -25,3 +25,20 @@ MP4Err autoCorrelation2nd_Neon(Float32 *alphar, Float32 *alphai, return 0; } +namespace rdar11688587 { + typedef float float32_t; + typedef __attribute__((neon_vector_type(4))) float32_t float32x4_t; + + template<int I> + float test() + { + extern float32x4_t vec; + return __extension__ ({ + float32x4_t __a = (vec); + (float32_t)__builtin_neon_vgetq_lane_f32(__a, I); // expected-error{{argument should be a value from 0 to 3}} + }); + } + + template float test<1>(); + template float test<4>(); // expected-note{{in instantiation of function template specialization 'rdar11688587::test<4>' requested here}} +} diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index b31763484489..4e1abc5e5bc8 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -143,7 +143,7 @@ namespace A { void g(int&); // expected-note{{type of 1st parameter of member declaration does not match definition ('int &' vs 'const int &')}} } -void A::f() {} // expected-error{{out-of-line definition of 'f' does not match any declaration in namespace 'A'}} +void A::f() {} // expected-error-re{{out-of-line definition of 'f' does not match any declaration in namespace 'A'$}} void A::g(const int&) { } // expected-error{{out-of-line definition of 'g' does not match any declaration in namespace 'A'}} @@ -286,3 +286,15 @@ protected: template <typename T> struct A2<T>::B::C; // expected-error {{no struct named 'C'}} } + +namespace PR13033 { +namespace NS { + int a; // expected-note {{'NS::a' declared here}} + int longer_b; //expected-note {{'NS::longer_b' declared here}} +} + +// Suggest adding a namespace qualifier to both variable names even though one +// is only a single character long. +int foobar = a + longer_b; // expected-error {{use of undeclared identifier 'a'; did you mean 'NS::a'?}} \ + // expected-error {{use of undeclared identifier 'longer_b'; did you mean 'NS::longer_b'?}} +} diff --git a/test/SemaCXX/no-rtti.cpp b/test/SemaCXX/no-rtti.cpp new file mode 100644 index 000000000000..75167050dca2 --- /dev/null +++ b/test/SemaCXX/no-rtti.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fno-rtti %s + +namespace std { + class type_info; +} + +void f() +{ + (void)typeid(int); // expected-error {{cannot use typeid with -fno-rtti}} +} diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index e3136039f425..d148f76698ec 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -33,8 +33,10 @@ nullptr_t f(nullptr_t null) // Operators (void)(null == nullptr); (void)(null <= nullptr); + (void)(null == 0); (void)(null == (void*)0); (void)((void*)0 == nullptr); + (void)(null <= 0); (void)(null <= (void*)0); (void)((void*)0 <= nullptr); (void)(0 == nullptr); @@ -44,7 +46,7 @@ nullptr_t f(nullptr_t null) (void)(1 > nullptr); // expected-error {{invalid operands to binary expression}} (void)(1 != nullptr); // expected-error {{invalid operands to binary expression}} (void)(1 + nullptr); // expected-error {{invalid operands to binary expression}} - (void)(0 ? nullptr : 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}} + (void)(0 ? nullptr : 0); (void)(0 ? nullptr : (void*)0); (void)(0 ? nullptr : A()); // expected-error {{non-pointer operand type 'A' incompatible with nullptr}} (void)(0 ? A() : nullptr); // expected-error {{non-pointer operand type 'A' incompatible with nullptr}} diff --git a/test/SemaCXX/offsetof-0x.cpp b/test/SemaCXX/offsetof-0x.cpp new file mode 100644 index 000000000000..610d919c1af1 --- /dev/null +++ b/test/SemaCXX/offsetof-0x.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof + +struct NonPOD { + virtual void f(); + int m; +}; + +struct P { + NonPOD fieldThatPointsToANonPODType; +}; + +void f() { + int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-warning{{offset of on non-standard-layout type 'P'}} +} + +struct StandardLayout { + int x; + StandardLayout() {} +}; +int o = __builtin_offsetof(StandardLayout, x); // no-warning diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index b5e121486621..615b10a43971 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -233,7 +233,7 @@ float* intref(const int&); void intref_test() { float* ir1 = intref(5); - float* ir2 = intref(5.5); // expected-warning{{implicit conversion turns literal floating-point number into integer}} + float* ir2 = intref(5.5); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 5.5 to 5}} } void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}} @@ -260,14 +260,12 @@ struct Z : X, Y { }; int& cvqual_subsume(X&); // expected-note{{candidate function}} float& cvqual_subsume(const Y&); // expected-note{{candidate function}} -int& cvqual_subsume2(const X&); // expected-note{{candidate function}} -float& cvqual_subsume2(const volatile Y&); // expected-note{{candidate function}} - -Z get_Z(); +int& cvqual_subsume2(X&); // expected-note{{candidate function}} +float& cvqual_subsume2(volatile Y&); // expected-note{{candidate function}} void cvqual_subsume_test(Z z) { cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous}} - int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous}} + cvqual_subsume2(z); // expected-error{{call to 'cvqual_subsume2' is ambiguous}} } // Test overloading with cv-qualification differences in reference @@ -319,14 +317,20 @@ namespace PR5756 { namespace test1 { template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}} - void foo(int n); // expected-note {{candidate function not viable: requires 1 argument, but 2 were provided}} - void foo(unsigned n = 10); // expected-note {{candidate function not viable: requires at most 1 argument, but 2 were provided}} void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} + // PR 11857 + void foo(int n); // expected-note {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} + void foo(unsigned n = 10); // expected-note {{candidate function not viable: allows at most single argument 'n', but 2 arguments were provided}} + void bar(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}} + void baz(int n = 0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}} + void test() { foo(4, "hello"); //expected-error {{no matching function for call to 'foo'}} + bar(); //expected-error {{no matching function for call to 'bar'}} + baz(3, 4, 5); // expected-error {{no matching function for call to 'baz'}} } } @@ -438,10 +442,10 @@ namespace PR6078 { namespace PR6177 { struct String { String(char const*); }; - void f(bool const volatile&); // expected-note{{passing argument to parameter here}} - void f(String); + void f(bool const volatile&); + int &f(String); - void g() { f(""); } // expected-error{{volatile lvalue reference to type 'const volatile bool' cannot bind to a value of unrelated type 'const char [1]'}} + void g() { int &r = f(""); } } namespace PR7095 { @@ -568,3 +572,11 @@ namespace PR12142 { void fun(int (*x)[10]); // expected-note{{candidate function not viable: 1st argument ('const int (*)[10]') would lose const qualifier}} void g() { fun((const int(*)[10])0); } // expected-error{{no matching function for call to 'fun'}} } + +// DR1152: Take 'volatile' into account when handling reference bindings in +// overload resolution. +namespace PR12931 { + void f(const int &, ...); + void f(const volatile int &, int); + void g() { f(0, 0); } +} diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp index 37c955201a98..09586201e561 100644 --- a/test/SemaCXX/overload-member-call.cpp +++ b/test/SemaCXX/overload-member-call.cpp @@ -72,8 +72,6 @@ namespace test1 { class A { template <class T> void foo(T t, unsigned N); // expected-note {{candidate function [with T = int] not viable: no known conversion from 'const char [6]' to 'unsigned int' for 2nd argument}} void foo(int n, char N); // expected-note {{candidate function not viable: no known conversion from 'const char [6]' to 'char' for 2nd argument}} - void foo(int n); // expected-note {{candidate function not viable: requires 1 argument, but 2 were provided}} - void foo(unsigned n = 10); // expected-note {{candidate function not viable: requires at most 1 argument, but 2 were provided}} void foo(int n, const char *s, int t); // expected-note {{candidate function not viable: requires 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, ...); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} void foo(int n, const char *s, int t, int u = 0); // expected-note {{candidate function not viable: requires at least 3 arguments, but 2 were provided}} @@ -83,6 +81,14 @@ namespace test1 { void baz(A &d); // expected-note {{candidate function not viable: 1st argument ('const test1::A') would lose const qualifier}} void baz(int i); // expected-note {{candidate function not viable: no known conversion from 'const test1::A' to 'int' for 1st argument}} + + // PR 11857 + void foo(int n); // expected-note {{candidate function not viable: requires single argument 'n', but 2 arguments were provided}} + void foo(unsigned n = 10); // expected-note {{candidate function not viable: allows at most single argument 'n', but 2 arguments were provided}} + void rab(double n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}} + void rab(int n, int u = 0); // expected-note {{candidate function not viable: requires at least argument 'n', but no arguments were provided}} + void zab(double n = 0.0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}} + void zab(int n = 0, int u = 0); // expected-note {{candidate function not viable: requires at most 2 arguments, but 3 were provided}} }; void test() { @@ -93,6 +99,9 @@ namespace test1 { b.bar(0); //expected-error {{no matching member function for call to 'bar'}} a.baz(b); //expected-error {{no matching member function for call to 'baz'}} + + a.rab(); //expected-error {{no matching member function for call to 'rab'}} + a.zab(3, 4, 5); //expected-error {{no matching member function for call to 'zab'}} } } diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp index b3c08085a695..ac110a3c0561 100644 --- a/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -174,7 +174,7 @@ void test_dr425(A a) { // FIXME: lots of candidates here! (void)(1.0f * a); // expected-error{{ambiguous}} \ // expected-note 4{{candidate}} \ - // expected-note {{remaining 77 candidates omitted; pass -fshow-overloads=all to show them}} + // expected-note {{remaining 117 candidates omitted; pass -fshow-overloads=all to show them}} } // pr5432 @@ -237,3 +237,34 @@ namespace PR7851 { (void)(x - x); } } + +namespace PR12854 { + enum { size = 1 }; + void plus_equals() { + int* __restrict py; + py += size; + } + + struct RestrictInt { + operator int* __restrict &(); + }; + + void user_conversions(RestrictInt ri) { + ++ri; + --ri; + ri++; + ri--; + } +} + +namespace PR12964 { + struct X { operator __int128() const; } x; + bool a = x == __int128(0); + bool b = x == 0; + + struct Y { operator unsigned __int128() const; } y; + bool c = y == __int128(0); + bool d = y == 0; + + bool e = x == y; +} diff --git a/test/SemaCXX/pr13353.cpp b/test/SemaCXX/pr13353.cpp new file mode 100644 index 000000000000..8fb5443fe623 --- /dev/null +++ b/test/SemaCXX/pr13353.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only %s +struct foo { + virtual void bar() ; +}; +template<typename T> +class zed : public foo { +}; +template<typename T> +class bah : public zed<T> { + void f() { + const_cast<foo *>(this->g())->bar(); + } +}; diff --git a/test/SemaCXX/pr13394-crash-on-invalid.cpp b/test/SemaCXX/pr13394-crash-on-invalid.cpp new file mode 100644 index 000000000000..413c52af858c --- /dev/null +++ b/test/SemaCXX/pr13394-crash-on-invalid.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// Don't crash (PR13394). + +namespace stretch_v1 { + struct closure_t { + const stretch_v1::ops_t* d_methods; // expected-error {{no type named 'ops_t' in namespace 'stretch_v1'}} + }; +} +namespace gatekeeper_v1 { + namespace gatekeeper_factory_v1 { + struct closure_t { // expected-note {{'closure_t' declared here}} + gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean 'closure_t'?}} + }; + } + gatekeeper_v1::closure_t *x; // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1}} +} diff --git a/test/SemaCXX/printf-block.cpp b/test/SemaCXX/printf-block.cpp new file mode 100644 index 000000000000..4a580037e731 --- /dev/null +++ b/test/SemaCXX/printf-block.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wformat -verify %s -Wno-error=non-pod-varargs + +int (^block) (int, const char *,...) __attribute__((__format__(__printf__,2,3))) = ^ __attribute__((__format__(__printf__,2,3))) (int arg, const char *format,...) {return 5;}; + +class HasNoCStr { + const char *str; + public: + HasNoCStr(const char *s): str(s) { } + const char *not_c_str() {return str;} +}; + +void test_block() { + const char str[] = "test"; + HasNoCStr hncs(str); + int n = 4; + block(n, "%s %d", str, n); // no-warning + block(n, "%s %s", hncs, n); // expected-warning{{cannot pass non-POD object of type 'HasNoCStr' to variadic block; expected type from format string was 'char *'}} expected-warning{{format specifies type 'char *' but the argument has type 'int'}} +} diff --git a/test/SemaCXX/printf-cstr.cpp b/test/SemaCXX/printf-cstr.cpp new file mode 100644 index 000000000000..a7eeb06b9c0e --- /dev/null +++ b/test/SemaCXX/printf-cstr.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -Wformat -verify %s -Wno-error=non-pod-varargs + +#include <stdarg.h> + +extern "C" { +extern int printf(const char *restrict, ...); +extern int sprintf(char *, const char *restrict, ...); +} + +class HasCStr { + const char *str; + public: + HasCStr(const char *s): str(s) { } + const char *c_str() {return str;} +}; + +class HasNoCStr { + const char *str; + public: + HasNoCStr(const char *s): str(s) { } + const char *not_c_str() {return str;} +}; + +extern const char extstr[16]; +void pod_test() { + char str[] = "test"; + char dest[32]; + char formatString[] = "non-const %s %s"; + HasCStr hcs(str); + HasNoCStr hncs(str); + int n = 10; + + printf("%d: %s\n", n, hcs.c_str()); + printf("%d: %s\n", n, hcs); // expected-warning{{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}} expected-note{{did you mean to call the c_str() method?}} + printf("%d: %s\n", n, hncs); // expected-warning{{cannot pass non-POD object of type 'HasNoCStr' to variadic function; expected type from format string was 'char *'}} + sprintf(str, "%d: %s", n, hcs); // expected-warning{{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}} expected-note{{did you mean to call the c_str() method?}} + + printf(formatString, hcs, hncs); // expected-warning{{cannot pass object of non-POD type 'HasCStr' through variadic function}} expected-warning{{cannot pass object of non-POD type 'HasNoCStr' through variadic function}} + printf(extstr, hcs, n); // expected-warning{{cannot pass object of non-POD type 'HasCStr' through variadic function}} +} + +struct Printf { + Printf(); + Printf(const Printf&); + Printf(const char *,...) __attribute__((__format__(__printf__,2,3))); +}; + +void constructor_test() { + const char str[] = "test"; + HasCStr hcs(str); + Printf p("%s %d %s", str, 10, 10); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}} + Printf q("%s %d", hcs, 10); // expected-warning {{cannot pass non-POD object of type 'HasCStr' to variadic constructor; expected type from format string was 'char *'}} expected-note{{did you mean to call the c_str() method?}} +} diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index d65a4684e629..a14193cc7ac8 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -86,14 +86,15 @@ namespace a { namespace a { namespace a { // A1 namespace a { // A2 - int i; + int i; // expected-note{{'::a::a::a::i' declared here}} } } } void test_a() { - a::a::i = 3; // expected-error{{no member named 'i'}} + a::a::i = 3; // expected-error{{no member named 'i' in namespace 'a::a'; did you mean '::a::a::a::i'?}} a::a::a::i = 4; + a::a::j = 3; // expected-error-re{{no member named 'j' in namespace 'a::a'$}} } struct Undef { // expected-note{{definition of 'Undef' is not complete until the closing '}'}} diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index 7f41b93a46e4..a4bc4325e655 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast %s +// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast -Wno-unused-volatile-lvalue %s #include <stdint.h> diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp index 364e4e4bef37..4a7560ba5b6a 100644 --- a/test/SemaCXX/static-assert.cpp +++ b/test/SemaCXX/static-assert.cpp @@ -34,3 +34,17 @@ static_assert(false, u"\U000317FF"); // expected-error {{static_assert failed u" static_assert(false, u8"Ω"); // expected-error {{static_assert failed u8"\316\251"}} static_assert(false, L"\u1234"); // expected-error {{static_assert failed L"\x1234"}} static_assert(false, L"\x1ff" "0\x123" "fx\xfffff" "goop"); // expected-error {{static_assert failed L"\x1FF""0\x123""fx\xFFFFFgoop"}} + +template<typename T> struct AlwaysFails { + // Only give one error here. + static_assert(false, ""); // expected-error {{static_assert failed}} +}; +AlwaysFails<int> alwaysFails; + +template<typename T> struct StaticAssertProtected { + static_assert(__is_literal(T), ""); // expected-error {{static_assert failed}} + static constexpr T t = {}; // no error here +}; +struct X { ~X(); }; +StaticAssertProtected<int> sap1; +StaticAssertProtected<X> sap2; // expected-note {{instantiation}} diff --git a/test/SemaCXX/switch-implicit-fallthrough-cxx98.cpp b/test/SemaCXX/switch-implicit-fallthrough-cxx98.cpp new file mode 100644 index 000000000000..14ffcef704d9 --- /dev/null +++ b/test/SemaCXX/switch-implicit-fallthrough-cxx98.cpp @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -Wimplicit-fallthrough %s + + +int fallthrough(int n) { + switch (n / 10) { + if (n - 1) { + n = 100; + } else if (n - 2) { + n = 101; + } else if (n - 3) { + n = 102; + } + case -1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + ; + case 0: {// expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + } + case 1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + n += 100 ; + case 3: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + if (n > 0) + n += 200; + case 4: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + if (n < 0) + ; + case 5: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + switch (n) { + case 111: + break; + case 112: + break; + case 113: + break ; + } + case 6: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + n += 300; + } + switch (n / 30) { + case 11: + case 12: // no warning here, intended fall-through, no statement between labels + n += 1600; + } + switch (n / 40) { + case 13: + if (n % 2 == 0) { + return 1; + } else { + return 2; + } + case 15: // no warning here, there's no fall-through + n += 3200; + } + switch (n / 50) { + case 17: { + if (n % 2 == 0) { + return 1; + } else { + return 2; + } + } + case 19: { // no warning here, there's no fall-through + n += 6400; + return 3; + } + case 21: { // no warning here, there's no fall-through + break; + } + case 23: // no warning here, there's no fall-through + n += 128000; + break; + case 25: // no warning here, there's no fall-through + break; + } + + return n; +} + +class ClassWithDtor { +public: + ~ClassWithDtor() {} +}; + +void fallthrough2(int n) { + switch (n) { + case 0: + { + ClassWithDtor temp; + break; + } + default: // no warning here, there's no fall-through + break; + } +} + +#define MY_SWITCH(X, Y, Z, U, V) switch (X) { case Y: Z; case U: V; } +#define MY_SWITCH2(X, Y, Z) switch (X) { Y; Z; } +#define MY_CASE(X, Y) case X: Y +#define MY_CASE2(X, Y, U, V) case X: Y; case U: V + +int fallthrough_macro1(int n) { + MY_SWITCH(n, 13, n *= 2, 14, break) // expected-warning{{unannotated fall-through between switch labels}} + + switch (n + 1) { + MY_CASE(33, n += 2); + MY_CASE(44, break); // expected-warning{{unannotated fall-through between switch labels}} + MY_CASE(55, n += 3); + } + + switch (n + 3) { + MY_CASE(333, return 333); + MY_CASE2(444, n += 44, 4444, break); // expected-warning{{unannotated fall-through between switch labels}} + MY_CASE(555, n += 33); + } + + MY_SWITCH2(n + 4, MY_CASE(17, n *= 3), MY_CASE(19, break)) // expected-warning{{unannotated fall-through between switch labels}} + + MY_SWITCH2(n + 5, MY_CASE(21, break), MY_CASE2(23, n *= 7, 25, break)) // expected-warning{{unannotated fall-through between switch labels}} + + return n; +} diff --git a/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp b/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp new file mode 100644 index 000000000000..7c52e5138b71 --- /dev/null +++ b/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough-per-function %s + + +int fallthrough(int n) { + switch (n / 10) { + case 0: + n += 100; + case 1: // expected-warning{{unannotated fall-through}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + switch (n) { + case 111: + n += 111; + [[clang::fallthrough]]; + case 112: + n += 112; + case 113: // expected-warning{{unannotated fall-through}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + n += 113; + break ; + } + } + return n; +} + +int fallthrough2(int n) { + switch (n / 10) { + case 0: + n += 100; + case 1: // no warning, as we didn't "opt-in" for it in this method + switch (n) { + case 111: + n += 111; + case 112: // no warning, as we didn't "opt-in" for it in this method + n += 112; + case 113: // no warning, as we didn't "opt-in" for it in this method + n += 113; + break ; + } + } + return n; +} + +void unscoped(int n) { + switch (n % 2) { + case 0: + // FIXME: This should be typo-corrected, probably. + [[fallthrough]]; + case 2: // expected-warning{{unannotated fall-through}} expected-note{{clang::fallthrough}} expected-note{{break;}} + [[clang::fallthrough]]; + case 1: + break; + } +} diff --git a/test/SemaCXX/switch-implicit-fallthrough.cpp b/test/SemaCXX/switch-implicit-fallthrough.cpp new file mode 100644 index 000000000000..cfc29c237c2d --- /dev/null +++ b/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -0,0 +1,197 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough %s + + +int fallthrough(int n) { + switch (n / 10) { + if (n - 1) { + n = 100; + } else if (n - 2) { + n = 101; + } else if (n - 3) { + n = 102; + } + case -1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + ; + case 0: {// expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + } + case 1: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + n += 100 ; + case 3: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + if (n > 0) + n += 200; + case 4: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + if (n < 0) + ; + case 5: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + switch (n) { + case 111: + break; + case 112: + break; + case 113: + break ; + } + case 6: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + n += 300; + case 66: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert 'break;' to avoid fall-through}} + break; + } + switch (n / 20) { + case 7: + n += 400; + [[clang::fallthrough]]; + case 9: // no warning here, intended fall-through marked with an attribute + n += 800; + [[clang::fallthrough]]; + default: { // no warning here, intended fall-through marked with an attribute + if (n % 2 == 0) { + return 1; + } else { + [[clang::fallthrough]]; + } + } + case 10: // no warning here, intended fall-through marked with an attribute + if (n % 3 == 0) { + n %= 3; + } else { + [[clang::fallthrough]]; + } + case 110: // expected-warning{{unannotated fall-through between switch labels}} but no fix-it hint as we have one fall-through annotation! + n += 800; + } + switch (n / 30) { + case 11: + case 12: // no warning here, intended fall-through, no statement between labels + n += 1600; + } + switch (n / 40) { + case 13: + if (n % 2 == 0) { + return 1; + } else { + return 2; + } + case 15: // no warning here, there's no fall-through + n += 3200; + } + switch (n / 50) { + case 17: { + if (n % 2 == 0) { + return 1; + } else { + return 2; + } + } + case 19: { // no warning here, there's no fall-through + n += 6400; + return 3; + } + case 21: { // no warning here, there's no fall-through + break; + } + case 23: // no warning here, there's no fall-through + n += 128000; + break; + case 25: // no warning here, there's no fall-through + break; + } + + return n; +} + +class ClassWithDtor { +public: + ~ClassWithDtor() {} +}; + +void fallthrough2(int n) { + switch (n) { + case 0: + { + ClassWithDtor temp; + break; + } + default: // no warning here, there's no fall-through + break; + } +} + +#define MY_SWITCH(X, Y, Z, U, V) switch (X) { case Y: Z; case U: V; } +#define MY_SWITCH2(X, Y, Z) switch (X) { Y; Z; } +#define MY_CASE(X, Y) case X: Y +#define MY_CASE2(X, Y, U, V) case X: Y; case U: V + +int fallthrough_macro1(int n) { + MY_SWITCH(n, 13, n *= 2, 14, break) // expected-warning{{unannotated fall-through between switch labels}} + + switch (n + 1) { + MY_CASE(33, n += 2); + MY_CASE(44, break); // expected-warning{{unannotated fall-through between switch labels}} + MY_CASE(55, n += 3); + } + + switch (n + 3) { + MY_CASE(333, return 333); + MY_CASE2(444, n += 44, 4444, break); // expected-warning{{unannotated fall-through between switch labels}} + MY_CASE(555, n += 33); + } + + MY_SWITCH2(n + 4, MY_CASE(17, n *= 3), MY_CASE(19, break)) // expected-warning{{unannotated fall-through between switch labels}} + + MY_SWITCH2(n + 5, MY_CASE(21, break), MY_CASE2(23, n *= 7, 25, break)) // expected-warning{{unannotated fall-through between switch labels}} + + return n; +} + +int fallthrough_position(int n) { + switch (n) { + [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} + case 221: + [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} + return 1; + [[clang::fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} + case 222: + [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} + n += 400; + case 223: // expected-warning{{unannotated fall-through between switch labels}} expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} expected-note{{insert 'break;' to avoid fall-through}} + [[clang::fallthrough]]; // expected-warning{{fallthrough annotation does not directly precede switch label}} + } + + // TODO: uncomment this test after CFG gets more options to deal with + // unreachable code: + // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20120507/057370.html +#if 0 + long p = static_cast<long>(n) * n; + switch (sizeof(p)) { + case 9: // this test will not work on compilers with 72-bit long + n += static_cast<int>(p >> 32); + [[clang::fallthrough]]; // no warning here + case 5: // it is not intended to work on compilers with 40-bit long as well + n += static_cast<int>(p); + break; + default: + break; + } +#endif + + return n; +} + +int fallthrough_targets(int n) { + [[clang::fallthrough]]; // expected-error{{fallthrough annotation is outside switch statement}} + + [[clang::fallthrough]] // expected-error{{fallthrough attribute is only allowed on empty statements}} + switch (n) { + case 121: + n += 400; + [[clang::fallthrough]]; // no warning here, correct target + case 123: + [[clang::fallthrough]] // expected-error{{fallthrough attribute is only allowed on empty statements}} + n += 800; + break; + [[clang::fallthrough]] // expected-error{{fallthrough attribute is only allowed on empty statements}} expected-note{{did you forget ';'?}} + case 125: + n += 1600; + } + return n; +} diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index f53939ac1790..54294bcbb8b1 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -131,25 +131,25 @@ void is_pod() { int arr[T(__is_pod(HasAnonymousUnion))]; } { int arr[T(__is_pod(Vector))]; } { int arr[T(__is_pod(VectorExt))]; } + { int arr[T(__is_pod(Derives))]; } + { int arr[T(__is_pod(DerivesAr))]; } + { int arr[T(__is_pod(DerivesArNB))]; } + { int arr[T(__is_pod(DerivesEmpty))]; } + { int arr[T(__is_pod(HasPriv))]; } + { int arr[T(__is_pod(HasProt))]; } + { int arr[T(__is_pod(DerivesHasPriv))]; } + { int arr[T(__is_pod(DerivesHasProt))]; } - { int arr[F(__is_pod(Derives))]; } - { int arr[F(__is_pod(DerivesAr))]; } - { int arr[F(__is_pod(DerivesArNB))]; } - { int arr[F(__is_pod(DerivesEmpty))]; } { int arr[F(__is_pod(HasCons))]; } { int arr[F(__is_pod(HasCopyAssign))]; } { int arr[F(__is_pod(HasMoveAssign))]; } { int arr[F(__is_pod(HasDest))]; } - { int arr[F(__is_pod(HasPriv))]; } - { int arr[F(__is_pod(HasProt))]; } { int arr[F(__is_pod(HasRef))]; } { int arr[F(__is_pod(HasVirt))]; } { int arr[F(__is_pod(DerivesHasCons))]; } { int arr[F(__is_pod(DerivesHasCopyAssign))]; } { int arr[F(__is_pod(DerivesHasMoveAssign))]; } { int arr[F(__is_pod(DerivesHasDest))]; } - { int arr[F(__is_pod(DerivesHasPriv))]; } - { int arr[F(__is_pod(DerivesHasProt))]; } { int arr[F(__is_pod(DerivesHasRef))]; } { int arr[F(__is_pod(DerivesHasVirt))]; } { int arr[F(__is_pod(NonPOD))]; } @@ -1223,10 +1223,10 @@ void has_trivial_copy_constructor() { { int arr[T(__has_trivial_copy(const Int))]; } { int arr[T(__has_trivial_copy(AllDefaulted))]; } { int arr[T(__has_trivial_copy(AllDeleted))]; } + { int arr[T(__has_trivial_copy(DerivesAr))]; } { int arr[F(__has_trivial_copy(HasCopy))]; } { int arr[F(__has_trivial_copy(HasTemplateCons))]; } - { int arr[F(__has_trivial_copy(DerivesAr))]; } { int arr[F(__has_trivial_copy(VirtAr))]; } { int arr[F(__has_trivial_copy(void))]; } { int arr[F(__has_trivial_copy(cvoid))]; } @@ -1250,13 +1250,13 @@ void has_trivial_copy_assignment() { { int arr[T(__has_trivial_assign(HasMoveAssign))]; } { int arr[T(__has_trivial_assign(AllDefaulted))]; } { int arr[T(__has_trivial_assign(AllDeleted))]; } + { int arr[T(__has_trivial_assign(DerivesAr))]; } { int arr[F(__has_trivial_assign(IntRef))]; } { int arr[F(__has_trivial_assign(HasCopyAssign))]; } { int arr[F(__has_trivial_assign(const Int))]; } { int arr[F(__has_trivial_assign(ConstIntAr))]; } { int arr[F(__has_trivial_assign(ConstIntArAr))]; } - { int arr[F(__has_trivial_assign(DerivesAr))]; } { int arr[F(__has_trivial_assign(VirtAr))]; } { int arr[F(__has_trivial_assign(void))]; } { int arr[F(__has_trivial_assign(cvoid))]; } @@ -1338,6 +1338,7 @@ void has_nothrow_assign() { { int arr[T(__has_nothrow_assign(HasVirtDest))]; } { int arr[T(__has_nothrow_assign(AllPrivate))]; } { int arr[T(__has_nothrow_assign(UsingAssign))]; } + { int arr[T(__has_nothrow_assign(DerivesAr))]; } { int arr[F(__has_nothrow_assign(IntRef))]; } { int arr[F(__has_nothrow_assign(HasCopyAssign))]; } @@ -1345,7 +1346,6 @@ void has_nothrow_assign() { { int arr[F(__has_nothrow_assign(const Int))]; } { int arr[F(__has_nothrow_assign(ConstIntAr))]; } { int arr[F(__has_nothrow_assign(ConstIntArAr))]; } - { int arr[F(__has_nothrow_assign(DerivesAr))]; } { int arr[F(__has_nothrow_assign(VirtAr))]; } { int arr[F(__has_nothrow_assign(void))]; } { int arr[F(__has_nothrow_assign(cvoid))]; } @@ -1375,18 +1375,15 @@ void has_nothrow_copy() { { int arr[T(__has_nothrow_copy(HasVirtDest))]; } { int arr[T(__has_nothrow_copy(HasTemplateCons))]; } { int arr[T(__has_nothrow_copy(AllPrivate))]; } + { int arr[T(__has_nothrow_copy(DerivesAr))]; } { int arr[F(__has_nothrow_copy(HasCopy))]; } { int arr[F(__has_nothrow_copy(HasMultipleCopy))]; } - { int arr[F(__has_nothrow_copy(DerivesAr))]; } { int arr[F(__has_nothrow_copy(VirtAr))]; } { int arr[F(__has_nothrow_copy(void))]; } { int arr[F(__has_nothrow_copy(cvoid))]; } } -template<bool b> struct assert_expr; -template<> struct assert_expr<true> {}; - void has_nothrow_constructor() { { int arr[T(__has_nothrow_constructor(Int))]; } { int arr[T(__has_nothrow_constructor(IntAr))]; } @@ -1415,11 +1412,6 @@ void has_nothrow_constructor() { { int arr[F(__has_nothrow_constructor(void))]; } { int arr[F(__has_nothrow_constructor(cvoid))]; } { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; } - - // While parsing an in-class initializer, the constructor is not known to be - // non-throwing yet. - struct HasInClassInit { int n = (assert_expr<!__has_nothrow_constructor(HasInClassInit)>(), 0); }; - { int arr[T(__has_nothrow_constructor(HasInClassInit))]; } } void has_virtual_destructor() { @@ -1582,6 +1574,8 @@ struct X0 { template<typename U> X0(const X0<U>&); }; +struct Abstract { virtual void f() = 0; }; + void is_convertible_to() { { int arr[T(__is_convertible_to(Int, Int))]; } { int arr[F(__is_convertible_to(Int, IntAr))]; } @@ -1606,6 +1600,7 @@ void is_convertible_to() { { int arr[F(__is_convertible_to(Function, Function))]; } { int arr[F(__is_convertible_to(PrivateCopy, PrivateCopy))]; } { int arr[T(__is_convertible_to(X0<int>, X0<float>))]; } + { int arr[F(__is_convertible_to(Abstract, Abstract))]; } } namespace is_convertible_to_instantiate { diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index b1e8d91d450d..893f08a422ca 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -190,3 +190,47 @@ namespace test1 { }; test1::FooBar *b; // expected-error{{no type named 'FooBar' in namespace 'test1'; did you mean 'Foobar'?}} } + +namespace ImplicitInt { + void f(int, unsinged); // expected-error{{did you mean 'unsigned'}} + struct S { + unsinged : 4; // expected-error{{did you mean 'unsigned'}} + }; +} + +namespace PR12951 { +// If there are two corrections that have the same identifier and edit distance +// and only differ by their namespaces, don't suggest either as a correction +// since both are equally likely corrections. +namespace foobar { struct Thing {}; } +namespace bazquux { struct Thing {}; } +void f() { Thing t; } // expected-error{{unknown type name 'Thing'}} +} + +namespace PR13051 { + template<typename T> struct S { + template<typename U> void f(); + operator bool() const; + }; + + void f() { + f(&S<int>::tempalte f<int>); // expected-error{{did you mean 'template'?}} + f(&S<int>::opeartor bool); // expected-error{{did you mean 'operator'?}} + f(&S<int>::foo); // expected-error-re{{no member named 'foo' in 'PR13051::S<int>'$}} + } +} + +namespace PR6325 { +class foo { }; // expected-note{{'foo' declared here}} +// Note that for this example (pulled from the PR), if keywords are not excluded +// as correction candidates then no suggestion would be given; correcting +// 'boo' to 'bool' is the same edit distance as correcting 'boo' to 'foo'. +class bar : boo { }; // expected-error{{unknown class name 'boo'; did you mean 'foo'?}} +} + +namespace bogus_keyword_suggestion { +void test() { + status = "OK"; // expected-error-re{{use of undeclared identifier 'status'$}} + return status; // expected-error-re{{use of undeclared identifier 'status'$}} + } +} diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index eb6428d631f2..687bfd2638d4 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -141,3 +141,9 @@ void test_bitcasts_2() { int y = (float &)x; // expected-warning {{uninitialized when used here}} } +void consume_const_ref(const int &n); +int test_const_ref() { + int n; // expected-note {{variable}} + consume_const_ref(n); + return n; // expected-warning {{uninitialized when used here}} +} diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 7879e7c7531f..13d287bf1af6 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -std=c++11 -verify %s int foo(int x); int bar(int* x); @@ -10,9 +10,6 @@ int far(const int& x); int a = a; // no-warning: used to signal intended lack of initialization. int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}} int c = (c + c); // expected-warning 2 {{variable 'c' is uninitialized when used within its own initialization}} -void test() { - int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}} -} int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}} int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}} @@ -24,6 +21,51 @@ int i = boo(i); int j = far(j); int k = __alignof__(k); +int l = k ? l : l; // expected-warning 2{{variable 'l' is uninitialized when used within its own initialization}} +int m = 1 + (k ? m : m); // expected-warning 2{{variable 'm' is uninitialized when used within its own initialization}} +int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}} + +void test_stuff () { + int a = a; // no-warning: used to signal intended lack of initialization. + int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}} + int c = (c + c); // expected-warning {{variable 'c' is uninitialized when used within its own initialization}} + int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}} + int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}} + int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}} + + // Thes don't warn as they don't require the value. + int g = sizeof(g); + void* ptr = &ptr; + int h = bar(&h); + int i = boo(i); + int j = far(j); + int k = __alignof__(k); + + int l = k ? l : l; // FIXME: warn here + int m = 1 + (k ? m : m); // FIXME: warn here + int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}} + + for (;;) { + int a = a; // no-warning: used to signal intended lack of initialization. + int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}} + int c = (c + c); // expected-warning {{variable 'c' is uninitialized when used within its own initialization}} + int d = ({ d + d ;}); // expected-warning {{variable 'd' is uninitialized when used within its own initialization}} + int e = static_cast<long>(e) + 1; // expected-warning {{variable 'e' is uninitialized when used within its own initialization}} + int f = foo(f); // expected-warning {{variable 'f' is uninitialized when used within its own initialization}} + + // Thes don't warn as they don't require the value. + int g = sizeof(g); + void* ptr = &ptr; + int h = bar(&h); + int i = boo(i); + int j = far(j); + int k = __alignof__(k); + + int l = k ? l : l; // FIXME: warn here + int m = 1 + (k ? m : m); // FIXME: warn here + int n = -n; // expected-warning {{variable 'n' is uninitialized when used within its own initialization}} + } +} // Test self-references with record types. class A { @@ -48,8 +90,9 @@ class A { A getA() { return A(); } A getA(int x) { return A(); } A getA(A* a) { return A(); } +A getA(A a) { return A(); } -void setupA() { +void setupA(bool x) { A a1; a1.set(a1.get()); A a2(a1.get()); @@ -69,8 +112,33 @@ void setupA() { A a15 = getA(a15.num); // expected-warning {{variable 'a15' is uninitialized when used within its own initialization}} A a16(&a16.num); // expected-warning {{variable 'a16' is uninitialized when used within its own initialization}} A a17(a17.get2()); // expected-warning {{variable 'a17' is uninitialized when used within its own initialization}} + A a18 = x ? a18 : a17; // expected-warning {{variable 'a18' is uninitialized when used within its own initialization}} + A a19 = getA(x ? a19 : a17); // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}} } +bool x; + +A a1; +A a2(a1.get()); +A a3(a1); +A a4(&a4); +A a5(a5.zero()); +A a6(a6.ONE); +A a7 = getA(); +A a8 = getA(a8.TWO); +A a9 = getA(&a9); +A a10(a10.count); + +A a11(a11); // expected-warning {{variable 'a11' is uninitialized when used within its own initialization}} +A a12(a12.get()); // expected-warning {{variable 'a12' is uninitialized when used within its own initialization}} +A a13(a13.num); // expected-warning {{variable 'a13' is uninitialized when used within its own initialization}} +A a14 = A(a14); // expected-warning {{variable 'a14' is uninitialized when used within its own initialization}} +A a15 = getA(a15.num); // expected-warning {{variable 'a15' is uninitialized when used within its own initialization}} +A a16(&a16.num); // expected-warning {{variable 'a16' is uninitialized when used within its own initialization}} +A a17(a17.get2()); // expected-warning {{variable 'a17' is uninitialized when used within its own initialization}} +A a18 = x ? a18 : a17; // expected-warning {{variable 'a18' is uninitialized when used within its own initialization}} +A a19 = getA(x ? a19 : a17); // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}} + struct B { // POD struct. int x; @@ -97,6 +165,7 @@ void setupB() { 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}} + B b10 = getB(-b10.x); // expected-warning {{variable 'b10' is uninitialized when used within its own initialization}} } // Also test similar constructs in a field's initializer. @@ -106,9 +175,9 @@ struct S { S(bool (*)[1]) : x(x) {} // expected-warning {{field is uninitialized when used here}} S(bool (*)[2]) : x(x + 1) {} // expected-warning {{field is uninitialized when used here}} - S(bool (*)[3]) : x(x + x) {} // expected-warning {{field is uninitialized when used here}} + S(bool (*)[3]) : x(x + x) {} // expected-warning 2{{field is uninitialized when used here}} S(bool (*)[4]) : x(static_cast<long>(x) + 1) {} // expected-warning {{field is uninitialized when used here}} - S(bool (*)[5]) : x(foo(x)) {} // FIXME: This should warn! + S(bool (*)[5]) : x(foo(x)) {} // expected-warning {{field is uninitialized when used here}} // These don't actually require the value of x and so shouldn't warn. S(char (*)[1]) : x(sizeof(x)) {} // rdar://8610363 @@ -164,6 +233,86 @@ int pr12325(int params) { // Test lambda expressions with -Wuninitialized int test_lambda() { - auto f1 = [] (int x, int y) { int z; return x + y + z; }; // expected-warning {{C++11 requires lambda with omitted result type to consist of a single return statement}} expected-warning{{variable 'z' is uninitialized when used here}} expected-note {{initialize the variable 'z' to silence this warning}} + auto f1 = [] (int x, int y) { int z; return x + y + z; }; // expected-warning{{variable 'z' is uninitialized when used here}} expected-note {{initialize the variable 'z' to silence this warning}} return f1(1, 2); } + +namespace { + struct A { + enum { A1 }; + static int A2() {return 5;} + int A3; + int A4() { return 5;} + }; + + struct B { + A a; + }; + + struct C { + C() {} + C(int x) {} + static A a; + B b; + }; + A C::a = A(); + + // Accessing non-static members will give a warning. + struct D { + C c; + D(char (*)[1]) : c(c.b.a.A1) {} + D(char (*)[2]) : c(c.b.a.A2()) {} + D(char (*)[3]) : c(c.b.a.A3) {} // expected-warning {{field is uninitialized when used here}} + D(char (*)[4]) : c(c.b.a.A4()) {} // expected-warning {{field is uninitialized when used here}} + + // c::a is static, so it is already initialized + D(char (*)[5]) : c(c.a.A1) {} + D(char (*)[6]) : c(c.a.A2()) {} + D(char (*)[7]) : c(c.a.A3) {} + D(char (*)[8]) : c(c.a.A4()) {} + }; + + struct E { + int a, b, c; + E(char (*)[1]) : a(a ? b : c) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[2]) : a(b ? a : a) {} // expected-warning 2{{field is uninitialized when used here}} + E(char (*)[3]) : a(b ? (a) : c) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[4]) : a(b ? c : (a+c)) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[5]) : a(b ? c : b) {} + + E(char (*)[6]) : a(a ?: a) {} // expected-warning 2{{field is uninitialized when used here}} + E(char (*)[7]) : a(b ?: a) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[8]) : a(a ?: c) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[9]) : a(b ?: c) {} + + E(char (*)[10]) : a((a, a, b)) {} + E(char (*)[11]) : a((c + a, a + 1, b)) {} // expected-warning 2{{field is uninitialized when used here}} + E(char (*)[12]) : a((b + c, c, a)) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[13]) : a((a, a, a, a)) {} // expected-warning {{field is uninitialized when used here}} + E(char (*)[14]) : a((b, c, c)) {} + }; + + struct F { + int a; + F* f; + F(int) {} + F() {} + }; + + int F::*ptr = &F::a; + F* F::*f_ptr = &F::f; + struct G { + F f1, f2; + F *f3, *f4; + G(char (*)[1]) : f1(f1) {} // expected-warning {{field is uninitialized when used here}} + G(char (*)[2]) : f2(f1) {} + G(char (*)[3]) : f2(F()) {} + + G(char (*)[4]) : f1(f1.*ptr) {} // expected-warning {{field is uninitialized when used here}} + G(char (*)[5]) : f2(f1.*ptr) {} + + G(char (*)[6]) : f3(f3) {} // expected-warning {{field is uninitialized when used here}} + G(char (*)[7]) : f3(f3->*f_ptr) {} // expected-warning {{field is uninitialized when used here}} + G(char (*)[8]) : f3(new F(f3->*ptr)) {} // expected-warning {{field is uninitialized when used here}} + }; +} diff --git a/test/SemaCXX/unknown-type-name.cpp b/test/SemaCXX/unknown-type-name.cpp index 5f8d8caae698..893e0cc5dc86 100644 --- a/test/SemaCXX/unknown-type-name.cpp +++ b/test/SemaCXX/unknown-type-name.cpp @@ -20,6 +20,13 @@ struct A { typedef T type; type f(); + + type g(); + + static int n; + static type m; + static int h(T::type, int); // expected-error{{missing 'typename'}} + static int h(T::type x, char); // expected-error{{missing 'typename'}} }; template<typename T> @@ -27,3 +34,52 @@ A<T>::type g(T t) { return t; } // expected-error{{missing 'typename'}} template<typename T> A<T>::type A<T>::f() { return type(); } // expected-error{{missing 'typename'}} + +template<typename T> +void f(T::type) { } // expected-error{{missing 'typename'}} + +template<typename T> +void g(T::type x) { } // expected-error{{missing 'typename'}} + +template<typename T> +void f(T::type, int) { } // expected-error{{missing 'typename'}} + +template<typename T> +void f(T::type x, char) { } // expected-error{{missing 'typename'}} + +template<typename T> +void f(int, T::type) { } // expected-error{{missing 'typename'}} + +template<typename T> +void f(char, T::type x) { } // expected-error{{missing 'typename'}} + +template<typename T> +void f(int, T::type, int) { } // expected-error{{missing 'typename'}} + +template<typename T> +void f(int, T::type x, char) { } // expected-error{{missing 'typename'}} + +template<typename T> int A<T>::n(T::value); // ok +template<typename T> +A<T>::type // expected-error{{missing 'typename'}} +A<T>::m(T::value, 0); // ok + +template<typename T> int A<T>::h(T::type, int) {} // expected-error{{missing 'typename'}} +template<typename T> int A<T>::h(T::type x, char) {} // expected-error{{missing 'typename'}} + +template<typename T> int h(T::type, int); // expected-error{{missing 'typename'}} +template<typename T> int h(T::type x, char); // expected-error{{missing 'typename'}} + +template<typename T> int junk1(T::junk); // expected-error{{declared as a template}} +template<typename T> int junk2(T::junk) throw(); // expected-error{{missing 'typename'}} +template<typename T> int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} expected-warning{{C++11}} +template<typename T> int junk4(T::junk j); // expected-error{{missing 'typename'}} + +// FIXME: We can tell this was intended to be a function because it does not +// have a dependent nested name specifier. +template<typename T> int i(T::type, int()); // expected-error{{variable 'i' declared as a template}} + +// FIXME: We know which type specifier should have been specified here. Provide +// a fix-it to add 'typename A<T>::type' +template<typename T> +A<T>::g() { } // expected-error{{requires a type specifier}} diff --git a/test/SemaCXX/unused.cpp b/test/SemaCXX/unused.cpp index 88783ce1a6b3..54898c828ec6 100644 --- a/test/SemaCXX/unused.cpp +++ b/test/SemaCXX/unused.cpp @@ -1,24 +1,36 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s + // PR4103 : Make sure we don't get a bogus unused expression warning -class APInt { - char foo; -}; -class APSInt : public APInt { - char bar; -public: - APSInt &operator=(const APSInt &RHS); -}; +namespace PR4103 { + class APInt { + char foo; + }; + class APSInt : public APInt { + char bar; + public: + APSInt &operator=(const APSInt &RHS); + }; -APSInt& APSInt::operator=(const APSInt &RHS) { - APInt::operator=(RHS); - return *this; -} + APSInt& APSInt::operator=(const APSInt &RHS) { + APInt::operator=(RHS); + return *this; + } -template<typename T> -struct X { - X(); -}; + template<typename T> + struct X { + X(); + }; + + void test() { + X<int>(); + } +} -void test() { - X<int>(); +namespace derefvolatile { + void f(volatile char* x) { + *x; // expected-warning {{expression result unused; assign into a variable to force a volatile load}} + (void)*x; // expected-warning {{expression result unused; assign into a variable to force a volatile load}} + volatile char y = 10; + (void)y; // don't warn here, because it's a common pattern. + } } diff --git a/test/SemaCXX/user-defined-conversions.cpp b/test/SemaCXX/user-defined-conversions.cpp index 43ec5a3d4ab9..284a31069288 100644 --- a/test/SemaCXX/user-defined-conversions.cpp +++ b/test/SemaCXX/user-defined-conversions.cpp @@ -69,7 +69,7 @@ void test_conversion(ConvertibleToBase ctb, ConvertibleToDerived ctd, } struct X1 { - X1(X1&); // expected-note{{candidate constructor not viable: no known conversion from 'X1' to 'X1 &' for 1st argument}} + X1(X1&); // expected-note{{candidate constructor not viable: expects an l-value for 1st argument}} }; struct X2 { diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp index ea7d203ca70f..a340e9d86b65 100644 --- a/test/SemaCXX/virtuals.cpp +++ b/test/SemaCXX/virtuals.cpp @@ -30,7 +30,7 @@ A fn(A) // expected-error{{parameter type 'A' is an abstract class}} \ // expected-error{{return type 'A' is an abstract class}} { A a; // expected-error{{variable type 'A' is an abstract class}} - (void)static_cast<A>(0); + (void)static_cast<A>(0); // expected-error{{allocating an object of abstract class type 'A'}} try { } catch(A) { // expected-error{{variable type 'A' is an abstract class}} } diff --git a/test/SemaCXX/warn-deprecated-header.cpp b/test/SemaCXX/warn-deprecated-header.cpp index f6ac2cb6393a..015e7751b93a 100644 --- a/test/SemaCXX/warn-deprecated-header.cpp +++ b/test/SemaCXX/warn-deprecated-header.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -fdeprecated-macro -verify %s // RUN: %clang_cc1 -fsyntax-only -Werror %s +// expected-warning@+2 {{This file is deprecated.}} #ifdef __DEPRECATED -#warning This file is deprecated. // expected-warning {{This file is deprecated.}} +#warning This file is deprecated. #endif diff --git a/test/SemaCXX/warn-literal-conversion.cpp b/test/SemaCXX/warn-literal-conversion.cpp index 5fcae5dc80e6..d7bec4c73e5b 100644 --- a/test/SemaCXX/warn-literal-conversion.cpp +++ b/test/SemaCXX/warn-literal-conversion.cpp @@ -5,29 +5,29 @@ void foo(int y); // Warn when a literal float or double is assigned or bound to an integer. void test0() { // Float - int y0 = 1.2222F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y1 = (1.2222F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y2 = (((1.2222F))); // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y3 = 12E-1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y4 = 1.23E1F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y0 = 1.2222F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y1 = (1.2222F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y2 = (((1.2222F))); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2222 to 1}} + int y3 = 12E-1F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} + int y4 = 1.23E1F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 12.3 to 12}} // Double - int y5 = 1.2222; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y6 = 12E-1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y7 = 1.23E1; // expected-warning {{implicit conversion turns literal floating-point number into integer}} - int y8 = (1.23E1); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y5 = 1.2222; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 1.2222 to 1}} + int y6 = 12E-1; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 1.2 to 1}} + int y7 = 1.23E1; // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} + int y8 = (1.23E1); // expected-warning {{implicit conversion from 'double' to 'int' changes value from 12.3 to 12}} // Test assignment to an existing variable. - y8 = 2.22F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + y8 = 2.22F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 2.22 to 2}} // Test direct initialization. - int y9(1.23F); // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y9(1.23F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.23 to 1}} // 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}} + foo(1.2F); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} - int y10 = -1.2F; // expected-warning {{implicit conversion turns literal floating-point number into integer}} + int y10 = -1.2F; // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.2 to 1}} - // -Wconversion-literal does NOT catch const values. + // -Wliteral-conversion does NOT catch const values. // (-Wconversion DOES catch them.) static const float sales_tax_rate = .095F; int z = sales_tax_rate; diff --git a/test/SemaCXX/warn-loop-analysis.cpp b/test/SemaCXX/warn-loop-analysis.cpp new file mode 100644 index 000000000000..627bc51d1b0f --- /dev/null +++ b/test/SemaCXX/warn-loop-analysis.cpp @@ -0,0 +1,154 @@ +// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s + +struct S { + bool stop() { return false; } + bool keep_running; +}; + +void by_ref(int &value) { } +void by_value(int value) { } +void by_pointer(int *value) {} + +void test1() { + S s; + for (; !s.stop();) {} + for (; s.keep_running;) {} + for (int i; i < 1; ++i) {} + for (int i; i < 1; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (int i; i < 1; ) { ++i; } + for (int i; i < 1; ) { return; } + for (int i; i < 1; ) { break; } + for (int i; i < 1; ) { goto exit_loop; } +exit_loop: + for (int i; i < 1; ) { by_ref(i); } + for (int i; i < 1; ) { by_value(i); } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (int i; i < 1; ) { by_pointer(&i); } + + for (int i; i < 1; ++i) + for (int j; j < 1; ++j) + { } + for (int i; i < 1; ++i) + for (int j; j < 1; ++i) // expected-warning {{variable 'j' used in loop condition not modified in loop body}} + { } + for (int i; i < 1; ++i) + for (int j; i < 1; ++j) // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + { } + + for (int *i, *j; i < j; ++i) {} + for (int *i, *j; i < j;) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + + // Dereferencing pointers is ignored for now. + for (int *i; *i; ) {} +} + +void test2() { + int i, j, k; + int *ptr; + + // Testing CastExpr + for (; i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i; ) { i = 5; } + + // Testing BinaryOperator + for (; i < j; ) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + for (; i < j; ) { i = 5; } + for (; i < j; ) { j = 5; } + + // Testing IntegerLiteral + for (; i < 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i < 5; ) { i = 5; } + + // Testing FloatingLiteral + for (; i < 5.0; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i < 5.0; ) { i = 5; } + + // Testing CharacterLiteral + for (; i == 'a'; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i == 'a'; ) { i = 5; } + + // Testing CXXBoolLiteralExpr + for (; i == true; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i == true; ) { i = 5; } + + // Testing GNUNullExpr + for (; ptr == __null; ) {} // expected-warning {{variable 'ptr' used in loop condition not modified in loop body}} + for (; ptr == __null; ) { ptr = &i; } + + // Testing UnaryOperator + for (; -i > 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; -i > 5; ) { ++i; } + + // Testing ImaginaryLiteral + for (; i != 3i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i != 3i; ) { ++i; } + + // Testing ConditionalOperator + for (; i ? j : k; ) {} // expected-warning {{variables 'i', 'j', and 'k' used in loop condition not modified in loop body}} + for (; i ? j : k; ) { ++i; } + for (; i ? j : k; ) { ++j; } + for (; i ? j : k; ) { ++k; } + for (; i; ) { j = i ? i : i; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i; ) { j = (i = 1) ? i : i; } + for (; i; ) { j = i ? i : ++i; } + + // Testing BinaryConditionalOperator + for (; i ?: j; ) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + for (; i ?: j; ) { ++i; } + for (; i ?: j; ) { ++j; } + for (; i; ) { j = i ?: i; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + + // Testing ParenExpr + for (; (i); ) { } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; (i); ) { ++i; } + + // Testing non-evaluated variables + for (; i < sizeof(j); ) { } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i < sizeof(j); ) { ++j; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + for (; i < sizeof(j); ) { ++i; } +} + +// False positive and how to silence. +void test3() { + int x; + int *ptr = &x; + for (;x<5;) { *ptr = 6; } // expected-warning {{variable 'x' used in loop condition not modified in loop body}} + + for (;x<5;) { + *ptr = 6; + (void)x; + } +} + +// Check ordering and printing of variables. Max variables is currently 4. +void test4() { + int a, b, c, d, e, f; + for (; a;); // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + for (; a + b;); // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + for (; a + b + c;); // expected-warning {{variables 'a', 'b', and 'c' used in loop condition not modified in loop body}} + for (; a + b + c + d;); // expected-warning {{variables 'a', 'b', 'c', and 'd' used in loop condition not modified in loop body}} + for (; a + b + c + d + e;); // expected-warning {{variables used in loop condition not modified in loop body}} + for (; a + b + c + d + e + f;); // expected-warning {{variables used in loop condition not modified in loop body}} + for (; a + c + d + b;); // expected-warning {{variables 'a', 'c', 'd', and 'b' used in loop condition not modified in loop body}} + for (; d + c + b + a;); // expected-warning {{variables 'd', 'c', 'b', and 'a' used in loop condition not modified in loop body}} +} + +// Ensure that the warning doesn't fail when lots of variables are used +// in the conditional. +void test5() { + for (int a; a+a+a+a+a+a+a+a+a+a;); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + for (int a; a+a+a+a+a+a+a+a+a+a+a;); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + for (int a; a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + for (int a; a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;);//\ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} +} + +// Ignore global variables and static variables. +int x6; +void test6() { + static int y; + for (;x6;); + for (;y;); +} diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp index e0d28da3d589..e388634e8840 100644 --- a/test/SemaCXX/warn-memset-bad-sizeof.cpp +++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -35,27 +35,27 @@ void f(Mat m, const Foo& const_foo, char *buffer) { /* Should warn */ memset(&s, 0, sizeof(&s)); // \ - // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + // expected-warning {{'memset' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} memset(ps, 0, sizeof(ps)); // \ - // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + // expected-warning {{'memset' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} memset(ps2, 0, sizeof(ps2)); // \ - // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + // expected-warning {{'memset' call operates on objects of type 'S' while the size is based on a different type 'PS' (aka 'S *')}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} memset(ps2, 0, sizeof(typeof(ps2))); // \ // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} memset(ps2, 0, sizeof(PS)); // \ // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} memset(heap_buffer, 0, sizeof(heap_buffer)); // \ - // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + // expected-warning {{'memset' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}} memcpy(&s, 0, sizeof(&s)); // \ - // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the destination}} + // expected-warning {{'memcpy' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} memcpy(0, &s, sizeof(&s)); // \ - // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the source}} + // expected-warning {{'memcpy' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} memmove(ps, 0, sizeof(ps)); // \ - // expected-warning {{argument to 'sizeof' in 'memmove' call is the same expression as the destination}} + // expected-warning {{'memmove' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} memcmp(ps, 0, sizeof(ps)); // \ - // expected-warning {{argument to 'sizeof' in 'memcmp' call is the same expression as the destination}} + // expected-warning {{'memcmp' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} /* Shouldn't warn */ memset((void*)&s, 0, sizeof(&s)); @@ -132,14 +132,14 @@ void strcpy_and_friends() { 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}} + // expected-warning {{'strncmp' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} strncasecmp(FOO, BAR, sizeof(FOO)); // \ - // expected-warning {{argument to 'sizeof' in 'strncasecmp' call is the same expression as the destination}} + // expected-warning {{'strncasecmp' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} char buff[80]; strncpy(buff, BAR, sizeof(BAR)); // \ - // expected-warning {{argument to 'sizeof' in 'strncpy' call is the same expression as the source}} + // expected-warning {{'strncpy' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} strndup(FOO, sizeof(FOO)); // \ - // expected-warning {{argument to 'sizeof' in 'strndup' call is the same expression as the source}} + // expected-warning {{'strndup' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} } diff --git a/test/SemaCXX/warn-static-function-inheader.cpp b/test/SemaCXX/warn-static-function-inheader.cpp new file mode 100644 index 000000000000..30386d9a258c --- /dev/null +++ b/test/SemaCXX/warn-static-function-inheader.cpp @@ -0,0 +1,12 @@ +#include "warn-static-function-inheader.h" +// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s +// rdar://11202617 + +static void another(void) { // expected-warning {{function 'another' is not needed and will not be emitted}} +} + +template <typename T> +void foo(void) { + thing(); + another(); +} diff --git a/test/SemaCXX/warn-static-function-inheader.h b/test/SemaCXX/warn-static-function-inheader.h new file mode 100644 index 000000000000..1c9e00b8bd22 --- /dev/null +++ b/test/SemaCXX/warn-static-function-inheader.h @@ -0,0 +1,3 @@ +static void thing(void) { // expected-warning {{'static' function 'thing' declared in header file should be declared 'static inline'}} +} + diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 566e5c1b843b..17a1931c1594 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 %s + +// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s +// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s #define LOCKABLE __attribute__ ((lockable)) #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) @@ -48,6 +51,30 @@ class __attribute__((scoped_lockable)) ReaderMutexLock { ~ReaderMutexLock() __attribute__((unlock_function)); }; +class SCOPED_LOCKABLE ReleasableMutexLock { + public: + ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu); + ~ReleasableMutexLock() UNLOCK_FUNCTION(); + + void Release() UNLOCK_FUNCTION(); +}; + + +template<class T> +class SmartPtr { +public: + SmartPtr(T* p) : ptr_(p) { } + SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { } + ~SmartPtr(); + + T* get() const { return ptr_; } + T* operator->() const { return ptr_; } + T& operator*() const { return *ptr_; } + +private: + T* ptr_; +}; + Mutex sls_mu; @@ -177,14 +204,11 @@ void sls_fun_bad_3() { void sls_fun_bad_4() { if (getBool()) - sls_mu.Lock(); // \ - expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \ - expected-note{{mutex acquired here}} - + sls_mu.Lock(); // expected-note{{mutex acquired here}} else - sls_mu2.Lock(); // \ - expected-note{{mutex acquired here}} -} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} + sls_mu2.Lock(); // expected-note{{mutex acquired here}} +} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \ + // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} void sls_fun_bad_5() { sls_mu.Lock(); // expected-note {{mutex acquired here}} @@ -225,15 +249,14 @@ void sls_fun_bad_7() { void sls_fun_bad_8() { sls_mu.Lock(); // expected-note{{mutex acquired here}} - // FIXME: TERRIBLE SOURCE LOCATION! - do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} - sls_mu.Unlock(); + do { + sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} } while (getBool()); } void sls_fun_bad_9() { do { - sls_mu.Lock(); // \ + sls_mu.Lock(); // \ // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \ // expected-note{{mutex acquired here}} } while (getBool()); @@ -241,15 +264,15 @@ void sls_fun_bad_9() { } void sls_fun_bad_10() { - sls_mu.Lock(); // expected-note 2{{mutex acquired here}} - while(getBool()) { - sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + sls_mu.Lock(); // expected-note 2{{mutex acquired here}} + while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + sls_mu.Unlock(); } } // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} void sls_fun_bad_11() { while (getBool()) { // \ - expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} sls_mu.Lock(); // expected-note {{mutex acquired here}} } sls_mu.Unlock(); // \ @@ -506,7 +529,7 @@ void late_bad_0() { LateFoo fooB; fooA.mu.Lock(); fooB.a = 5; // \ - // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} + // expected-warning{{writing variable 'a' requires locking 'fooB.mu' exclusively}} fooA.mu.Unlock(); } @@ -516,7 +539,7 @@ void late_bad_1() { 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'}} + // expected-warning{{reading the value pointed to by 'q' requires locking 'b1.mu'}} b1.mu1_.Unlock(); b1.b_ = res; mu.Unlock(); @@ -526,7 +549,7 @@ void late_bad_2() { LateBar BarA; BarA.FooPointer->mu.Lock(); BarA.Foo.a = 2; // \ - // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} + // expected-warning{{writing variable 'a' requires locking 'BarA.Foo.mu' exclusively}} BarA.FooPointer->mu.Unlock(); } @@ -534,7 +557,7 @@ void late_bad_3() { LateBar BarA; BarA.Foo.mu.Lock(); BarA.FooPointer->a = 2; // \ - // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} + // expected-warning{{writing variable 'a' requires locking 'BarA.FooPointer->mu' exclusively}} BarA.Foo.mu.Unlock(); } @@ -542,7 +565,7 @@ void late_bad_4() { LateBar BarA; BarA.Foo.mu.Lock(); BarA.Foo2.a = 2; // \ - // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} + // expected-warning{{writing variable 'a' requires locking 'BarA.Foo2.mu' exclusively}} BarA.Foo.mu.Unlock(); } @@ -1176,13 +1199,13 @@ void main() { Foo f1, *f2; f1.mu_.Lock(); - f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}} + f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.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->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is locked}} f2->mu_.Unlock(); mu2.Lock(); w = 2; @@ -1210,7 +1233,7 @@ void func() { b1->MyLock(); b1->a_ = 5; - b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}} + b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'b2->mu1_' exclusively}} b2->MyLock(); b2->MyUnlock(); b1->MyUnlock(); @@ -1239,12 +1262,12 @@ int func(int i) { int x; b3->mu1_.Lock(); - res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \ + res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'b1.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}} + // expected-warning {{writing variable 'a_' requires locking 'b1.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'}} @@ -1269,8 +1292,8 @@ class Foo { 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}} + child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'child->lock_'}} + child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'child->lock_' exclusively}} lock_.Unlock(); } @@ -1307,7 +1330,7 @@ void Foo::Func(Foo* child) { lock_.Lock(); child->lock_.Lock(); - child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}} + child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is locked}} child->bar(7); child->a_ = 5; child->lock_.Unlock(); @@ -1355,8 +1378,8 @@ 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'}} + foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu2'}} \ + // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu1'}} } } // end namespace thread_annot_lock_42 @@ -1379,14 +1402,14 @@ void main() { Child *c; Base *b = c; - b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}} + b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'b->mu_'}} b->mu_.Lock(); - b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}} + b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is locked}} b->mu_.Unlock(); - c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}} + c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'c->mu_'}} c->mu_.Lock(); - c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}} + c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is locked}} c->mu_.Unlock(); } } // end namespace thread_annot_lock_46 @@ -1413,9 +1436,9 @@ int Foo::method1(int i) { void main() { Foo a; - a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \ + a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'a.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 'a.mu2'}} \ // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}} } } // end namespace thread_annot_lock_67_modified @@ -1461,14 +1484,14 @@ namespace substitution_test { DataLocker dlr; dlr.lockData(d1); // expected-note {{mutex acquired here}} dlr.unlockData(d2); // \ - // expected-warning {{unlocking 'mu' that was not locked}} - } // expected-warning {{mutex 'mu' is still locked at the end of function}} + // expected-warning {{unlocking 'd2->mu' that was not locked}} + } // expected-warning {{mutex 'd1->mu' is still locked at the end of function}} void bar4(MyData* d1, MyData* d2) { DataLocker dlr; dlr.lockData(d1); foo(d2); // \ - // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}} + // expected-warning {{calling function 'foo' requires exclusive lock on 'd2->mu'}} dlr.unlockData(d1); } }; @@ -1527,7 +1550,7 @@ namespace template_member_test { struct IndirectLock { int DoNaughtyThings(T *t) { u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}} - return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}} + return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}} } }; @@ -1543,7 +1566,7 @@ namespace template_member_test { template<typename U> struct W { V v; void f(U u) { - v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}} + v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'v.m'}} } }; template struct W<int>; // expected-note {{here}} @@ -1581,7 +1604,7 @@ struct TestScopedLockable { MutexLock mulock_a(&mu1); MutexLock mulock_b(&mu1); // \ // expected-warning {{locking 'mu1' that is already locked}} - } // expected-warning {{unlocking 'mu1' that was not locked}} + } void foo4() { MutexLock mulock1(&mu1), mulock2(&mu2); @@ -1606,7 +1629,7 @@ Foo fooObj; void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_); void bar() { - foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} + foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}} fooObj.mu_.Lock(); foo(); fooObj.mu_.Unlock(); @@ -1679,7 +1702,7 @@ struct TestTryLock { bool b2 = b; if (cond) b = true; - if (b) { // b should be unknown at this point, becuase of the join point + if (b) { // b should be unknown at this point, because of the join point a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}} } if (b2) { // b2 should be known at this point. @@ -1806,7 +1829,7 @@ void test() { f1.mu_.Unlock(); bt.barTD(&f1); // \ - // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}} bt.fooBase.mu_.Unlock(); bt.fooBaseT.mu_.Unlock(); @@ -1814,7 +1837,7 @@ void test() { Cell<int> cell; cell.data = 0; // \ - // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}} cell.foo(); cell.mu_.Lock(); cell.fooEx(); @@ -1883,7 +1906,7 @@ void Foo::foo1(Foo *f_defined) { void test() { Foo myfoo; myfoo.foo1(&myfoo); // \ - // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}} myfoo.mu_.Lock(); myfoo.foo1(&myfoo); myfoo.mu_.Unlock(); @@ -1998,29 +2021,28 @@ void test() { Foo myFoo; myFoo.foo2(); // \ - // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}} myFoo.foo3(&myFoo); // \ - // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}} myFoo.fooT1(dummy); // \ - // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}} - // FIXME: uncomment with template instantiation of attributes patch - // myFoo.fooT2(dummy); // expected warning + myFoo.fooT2(dummy); // \ + // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}} fooF1(&myFoo); // \ - // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}} fooF2(&myFoo); // \ - // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}} fooF3(&myFoo); // \ - // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}} myFoo.mu_.Lock(); myFoo.foo2(); myFoo.foo3(&myFoo); myFoo.fooT1(dummy); - // FIXME: uncomment with template instantiation of attributes patch - // myFoo.fooT2(dummy); + myFoo.fooT2(dummy); fooF1(&myFoo); fooF2(&myFoo); @@ -2029,7 +2051,7 @@ void test() { FooT<int> myFooT; myFooT.foo(); // \ - // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} + // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}} } } // end namespace FunctionDefinitionTest @@ -2213,31 +2235,887 @@ void test() { bar.getFoo().mu_.Lock(); bar.getFooey().a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}} bar.getFoo().mu_.Unlock(); bar.getFoo2(a).mu_.Lock(); bar.getFoo2(b).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}} bar.getFoo2(a).mu_.Unlock(); bar.getFoo3(a, b).mu_.Lock(); bar.getFoo3(a, c).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}} bar.getFoo3(a, b).mu_.Unlock(); getBarFoo(bar, a).mu_.Lock(); getBarFoo(bar, b).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}} getBarFoo(bar, a).mu_.Unlock(); (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}} (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); } -} // end namespace +} // end namespace MoreLockExpressions + + +namespace TrylockJoinPoint { + +class Foo { + Mutex mu; + bool c; + + void foo() { + if (c) { + if (!mu.TryLock()) + return; + } else { + mu.Lock(); + } + mu.Unlock(); + } +}; + +} // end namespace TrylockJoinPoint + + +namespace LockReturned { + +class Foo { +public: + int a GUARDED_BY(mu_); + void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_); + void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_); + + static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_); + + Mutex* getMu() LOCK_RETURNED(mu_); + + Mutex mu_; + + static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_); +}; + + +// Calls getMu() directly to lock and unlock +void test1(Foo* f1, Foo* f2) { + f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}} + f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}} + + f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \ + // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} + Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}} + + f1->getMu()->Lock(); + + f1->a = 0; + f1->foo(); + f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} + + Foo::getMu(f2)->Lock(); + f1->foo2(f2); + Foo::getMu(f2)->Unlock(); + + Foo::sfoo(f1); + + f1->getMu()->Unlock(); +} + + +Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f)); + +class Bar : public Foo { +public: + int b GUARDED_BY(getMu()); + void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu()); + void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu()); + + static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu()); + static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g)); +}; + + + +// Use getMu() within other attributes. +// This requires at lest levels of substitution, more in the case of +void test2(Bar* b1, Bar* b2) { + b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}} + b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}} + b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \ + // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} + Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}} + Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}} + + b1->getMu()->Lock(); + + b1->b = 0; + b1->bar(); + b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} + + b2->getMu()->Lock(); + b1->bar2(b2); + + b2->getMu()->Unlock(); + + Bar::sbar(b1); + Bar::sbar2(b1); + + b1->getMu()->Unlock(); +} + + +// Sanity check -- lock the mutex directly, but use attributes that call getMu() +// Also lock the mutex using getFooMu, which calls a lock_returned function. +void test3(Bar* b1, Bar* b2) { + b1->mu_.Lock(); + b1->b = 0; + b1->bar(); + + getFooMu(b2)->Lock(); + b1->bar2(b2); + getFooMu(b2)->Unlock(); + + Bar::sbar(b1); + Bar::sbar2(b1); + + b1->mu_.Unlock(); +} + +} // end namespace LockReturned + + +namespace ReleasableScopedLock { + +class Foo { + Mutex mu_; + bool c; + int a GUARDED_BY(mu_); + + void test1(); + void test2(); + void test3(); + void test4(); + void test5(); +}; + + +void Foo::test1() { + ReleasableMutexLock rlock(&mu_); + rlock.Release(); +} + +void Foo::test2() { + ReleasableMutexLock rlock(&mu_); + if (c) { // test join point -- held/not held during release + rlock.Release(); + } +} + +void Foo::test3() { + ReleasableMutexLock rlock(&mu_); + a = 0; + rlock.Release(); + a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} +} + +void Foo::test4() { + ReleasableMutexLock rlock(&mu_); + rlock.Release(); + rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}} +} + +void Foo::test5() { + ReleasableMutexLock rlock(&mu_); + if (c) { + rlock.Release(); + } + // no warning on join point for managed lock. + rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}} +} + + +} // end namespace ReleasableScopedLock + + +namespace TrylockFunctionTest { + +class Foo { +public: + Mutex mu1_; + Mutex mu2_; + bool c; + + bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_); +}; + +bool Foo::lockBoth() { + if (!mu1_.TryLock()) + return false; + + mu2_.Lock(); + if (!c) { + mu1_.Unlock(); + mu2_.Unlock(); + return false; + } + + return true; +} + + +} // end namespace TrylockFunctionTest + + + +namespace DoubleLockBug { + +class Foo { +public: + Mutex mu_; + int a GUARDED_BY(mu_); + + void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_); + int foo2() SHARED_LOCKS_REQUIRED(mu_); +}; + + +void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) { + a = 0; +} + +int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) { + return a; +} + +} + + + +namespace UnlockBug { + +class Foo { +public: + Mutex mutex_; + + void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}} + mutex_.Unlock(); + } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}} + + + void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}} + mutex_.Unlock(); + } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}} +}; + +} // end namespace UnlockBug + + + +namespace FoolishScopedLockableBug { + +class SCOPED_LOCKABLE WTF_ScopedLockable { +public: + WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu); + + // have to call release() manually; + ~WTF_ScopedLockable(); + + void release() UNLOCK_FUNCTION(); +}; + + +class Foo { + Mutex mu_; + int a GUARDED_BY(mu_); + bool c; + + void doSomething(); + + void test1() { + WTF_ScopedLockable wtf(&mu_); + wtf.release(); + } + + void test2() { + WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}} + } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + + void test3() { + if (c) { + WTF_ScopedLockable wtf(&mu_); + wtf.release(); + } + } + + void test4() { + if (c) { + doSomething(); + } + else { + WTF_ScopedLockable wtf(&mu_); + wtf.release(); + } + } + + void test5() { + if (c) { + WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}} + } + } // expected-warning {{mutex 'mu_' is not locked on every path through here}} + + void test6() { + if (c) { + doSomething(); + } + else { + WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}} + } + } // expected-warning {{mutex 'mu_' is not locked on every path through here}} +}; + + +} // end namespace FoolishScopedLockableBug + + + +namespace TemporaryCleanupExpr { + +class Foo { + int a GUARDED_BY(getMutexPtr().get()); + + SmartPtr<Mutex> getMutexPtr(); + + void test(); +}; + + +void Foo::test() { + { + ReaderMutexLock lock(getMutexPtr().get()); + int b = a; + } + int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}} +} + +} // end namespace TemporaryCleanupExpr + + + +namespace SmartPointerTests { + +class Foo { +public: + SmartPtr<Mutex> mu_; + int a GUARDED_BY(mu_); + int b GUARDED_BY(mu_.get()); + int c GUARDED_BY(*mu_); + + void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_); + void Unlock() UNLOCK_FUNCTION(mu_); + + void test0(); + void test1(); + void test2(); + void test3(); + void test4(); + void test5(); + void test6(); + void test7(); + void test8(); +}; + +void Foo::test0() { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}} + c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}} +} + +void Foo::test1() { + mu_->Lock(); + a = 0; + b = 0; + c = 0; + mu_->Unlock(); +} + +void Foo::test2() { + (*mu_).Lock(); + a = 0; + b = 0; + c = 0; + (*mu_).Unlock(); +} + + +void Foo::test3() { + mu_.get()->Lock(); + a = 0; + b = 0; + c = 0; + mu_.get()->Unlock(); +} + + +void Foo::test4() { + MutexLock lock(mu_.get()); + a = 0; + b = 0; + c = 0; +} + + +void Foo::test5() { + MutexLock lock(&(*mu_)); + a = 0; + b = 0; + c = 0; +} + + +void Foo::test6() { + Lock(); + a = 0; + b = 0; + c = 0; + Unlock(); +} + + +void Foo::test7() { + { + Lock(); + mu_->Unlock(); + } + { + mu_->Lock(); + Unlock(); + } + { + mu_.get()->Lock(); + mu_->Unlock(); + } + { + mu_->Lock(); + mu_.get()->Unlock(); + } + { + mu_.get()->Lock(); + (*mu_).Unlock(); + } + { + (*mu_).Lock(); + mu_->Unlock(); + } +} + + +void Foo::test8() { + mu_->Lock(); + mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}} + (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}} + mu_.get()->Unlock(); + Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}} +} + + +class Bar { + SmartPtr<Foo> foo; + + void test0(); + void test1(); + void test2(); + void test3(); +}; + + +void Bar::test0() { + foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}} + (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}} + foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}} +} + + +void Bar::test1() { + foo->mu_->Lock(); + foo->a = 0; + (*foo).b = 0; + foo.get()->c = 0; + foo->mu_->Unlock(); +} + + +void Bar::test2() { + (*foo).mu_->Lock(); + foo->a = 0; + (*foo).b = 0; + foo.get()->c = 0; + foo.get()->mu_->Unlock(); +} + + +void Bar::test3() { + MutexLock lock(foo->mu_.get()); + foo->a = 0; + (*foo).b = 0; + foo.get()->c = 0; +} + +} // end namespace SmartPointerTests + + + +namespace DuplicateAttributeTest { + +class LOCKABLE Foo { +public: + Mutex mu1_; + Mutex mu2_; + Mutex mu3_; + int a GUARDED_BY(mu1_); + int b GUARDED_BY(mu2_); + int c GUARDED_BY(mu3_); + + void lock() EXCLUSIVE_LOCK_FUNCTION(); + void unlock() UNLOCK_FUNCTION(); + + void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_); + void slock1() SHARED_LOCK_FUNCTION(mu1_); + void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_); + void locklots() + EXCLUSIVE_LOCK_FUNCTION(mu1_) + EXCLUSIVE_LOCK_FUNCTION(mu2_) + EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_); + + void unlock1() UNLOCK_FUNCTION(mu1_); + void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_); + void unlocklots() + UNLOCK_FUNCTION(mu1_) + UNLOCK_FUNCTION(mu2_) + UNLOCK_FUNCTION(mu1_, mu2_, mu3_); +}; + + +void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { } +void Foo::unlock() UNLOCK_FUNCTION() { } + +void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) { + mu1_.Lock(); +} + +void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) { + mu1_.Lock(); +} + +void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) { + mu1_.Lock(); + mu2_.Lock(); + mu3_.Lock(); +} + +void Foo::locklots() + EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_) + EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) { + mu1_.Lock(); + mu2_.Lock(); + mu3_.Lock(); +} + +void Foo::unlock1() UNLOCK_FUNCTION(mu1_) { + mu1_.Unlock(); +} + +void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) { + mu1_.Unlock(); + mu2_.Unlock(); + mu3_.Unlock(); +} + +void Foo::unlocklots() + UNLOCK_FUNCTION(mu1_, mu2_) + UNLOCK_FUNCTION(mu2_, mu3_) { + mu1_.Unlock(); + mu2_.Unlock(); + mu3_.Unlock(); +} + + +void test0() { + Foo foo; + foo.lock(); + foo.unlock(); + + foo.lock(); + foo.lock(); // expected-warning {{locking 'foo' that is already locked}} + foo.unlock(); + foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}} +} + + +void test1() { + Foo foo; + foo.lock1(); + foo.a = 0; + foo.unlock1(); + + foo.lock1(); + foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}} + foo.a = 0; + foo.unlock1(); + foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}} +} + + +int test2() { + Foo foo; + foo.slock1(); + int d1 = foo.a; + foo.unlock1(); + + foo.slock1(); + foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}} + int d2 = foo.a; + foo.unlock1(); + foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}} + return d1 + d2; +} + + +void test3() { + Foo foo; + foo.lock3(); + foo.a = 0; + foo.b = 0; + foo.c = 0; + foo.unlock3(); + + foo.lock3(); + foo.lock3(); // \ + // expected-warning {{locking 'foo.mu1_' that is already locked}} \ + // expected-warning {{locking 'foo.mu2_' that is already locked}} \ + // expected-warning {{locking 'foo.mu3_' that is already locked}} + foo.a = 0; + foo.b = 0; + foo.c = 0; + foo.unlock3(); + foo.unlock3(); // \ + // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \ + // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \ + // expected-warning {{unlocking 'foo.mu3_' that was not locked}} +} + + +void testlots() { + Foo foo; + foo.locklots(); + foo.a = 0; + foo.b = 0; + foo.c = 0; + foo.unlocklots(); + + foo.locklots(); + foo.locklots(); // \ + // expected-warning {{locking 'foo.mu1_' that is already locked}} \ + // expected-warning {{locking 'foo.mu2_' that is already locked}} \ + // expected-warning {{locking 'foo.mu3_' that is already locked}} + foo.a = 0; + foo.b = 0; + foo.c = 0; + foo.unlocklots(); + foo.unlocklots(); // \ + // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \ + // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \ + // expected-warning {{unlocking 'foo.mu3_' that was not locked}} +} + +} // end namespace DuplicateAttributeTest + + + +namespace TryLockEqTest { + +class Foo { + Mutex mu_; + int a GUARDED_BY(mu_); + bool c; + + int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_); + Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_); + void unlock() UNLOCK_FUNCTION(mu_); + + void test1(); + void test2(); +}; + + +void Foo::test1() { + if (tryLockMutexP() == 0) { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + return; + } + a = 0; + unlock(); + + if (tryLockMutexP() != 0) { + a = 0; + unlock(); + } + + if (0 != tryLockMutexP()) { + a = 0; + unlock(); + } + + if (!(tryLockMutexP() == 0)) { + a = 0; + unlock(); + } + + if (tryLockMutexI() == 0) { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + return; + } + a = 0; + unlock(); + + if (0 == tryLockMutexI()) { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + return; + } + a = 0; + unlock(); + + if (tryLockMutexI() == 1) { + a = 0; + unlock(); + } + + if (mu_.TryLock() == false) { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + return; + } + a = 0; + unlock(); + + if (mu_.TryLock() == true) { + a = 0; + unlock(); + } + else { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + } + +#if __has_feature(cxx_nullptr) + if (tryLockMutexP() == nullptr) { + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + return; + } + a = 0; + unlock(); +#endif +} + + +void Foo::test2() { +/* FIXME: these tests depend on changes to the CFG. + * + if (mu_.TryLock() && c) { + a = 0; + unlock(); + } + else return; + + if (c && mu_.TryLock()) { + a = 0; + unlock(); + } + else return; + + if (!(mu_.TryLock() && c)) + return; + a = 0; + unlock(); + + if (!(c && mu_.TryLock())) + return; + a = 0; + unlock(); + + if (!(mu_.TryLock() == 0) && c) { + a = 0; + unlock(); + } + + if (!mu_.TryLock() || c) + return; + a = 0; + unlock(); +*/ +} + +} // end namespace TryLockEqTest + + +namespace ExistentialPatternMatching { + +class Graph { +public: + Mutex mu_; +}; + +void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_); +void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_); + +class Node { +public: + int a GUARDED_BY(&Graph::mu_); + + void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) { + a = 0; + } + void foo2() LOCKS_EXCLUDED(&Graph::mu_); +}; + +void test() { + Graph g1; + Graph g2; + Node n1; + + n1.a = 0; // expected-warning {{writing variable 'a' requires locking '&ExistentialPatternMatching::Graph::mu_' exclusively}} + n1.foo(); // expected-warning {{calling function 'foo' requires exclusive lock on '&ExistentialPatternMatching::Graph::mu_'}} + n1.foo2(); + + g1.mu_.Lock(); + n1.a = 0; + n1.foo(); + n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}} + g1.mu_.Unlock(); + + g2.mu_.Lock(); + n1.a = 0; + n1.foo(); + n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}} + g2.mu_.Unlock(); + + LockAllGraphs(); + n1.a = 0; + n1.foo(); + n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}} + UnlockAllGraphs(); + + LockAllGraphs(); + g1.mu_.Unlock(); + + LockAllGraphs(); + g2.mu_.Unlock(); + + LockAllGraphs(); + g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}} + g1.mu_.Unlock(); +} +} // end namespace ExistentialPatternMatching diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index c2fa1d77a01a..3f8a7359088d 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -22,7 +22,7 @@ #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) -class __attribute__((lockable)) Mu { +class LOCKABLE Mutex { public: void Lock(); }; @@ -32,11 +32,11 @@ class UnlockableMu{ class MuWrapper { public: - Mu mu; - Mu getMu() { + Mutex mu; + Mutex getMu() { return mu; } - Mu * getMuPointer() { + Mutex * getMuPointer() { return μ } }; @@ -50,32 +50,32 @@ class MuDoubleWrapper { } }; -Mu mu1; +Mutex mu1; UnlockableMu umu; -Mu mu2; +Mutex mu2; MuWrapper muWrapper; MuDoubleWrapper muDoubleWrapper; -Mu* muPointer; -Mu ** muDoublePointer = & muPointer; -Mu& muRef = mu1; +Mutex* muPointer; +Mutex** muDoublePointer = & muPointer; +Mutex& muRef = mu1; //---------------------------------------// // Scoping tests //--------------------------------------// class Foo { - Mu foomu; - void needLock() __attribute__((exclusive_lock_function(foomu))); + Mutex foomu; + void needLock() EXCLUSIVE_LOCK_FUNCTION(foomu); }; class Foo2 { - void needLock() __attribute__((exclusive_lock_function(foomu))); - Mu foomu; + void needLock() EXCLUSIVE_LOCK_FUNCTION(foomu); + Mutex foomu; }; class Bar { - Mu barmu; - Mu barmu2 __attribute__((acquired_after(barmu))); + Mutex barmu; + Mutex barmu2 ACQUIRED_AFTER(barmu); }; @@ -90,34 +90,34 @@ class Bar { #error "Should support no_thread_safety_analysis attribute" #endif -void noanal_fun() __attribute__((no_thread_safety_analysis)); +void noanal_fun() 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) NO_THREAD_SAFETY_ANALYSIS; int noanal_testfn(int y) { - int x __attribute__((no_thread_safety_analysis)) = y; // \ + int x 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)); // \ +int noanal_test_var 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)); // \ + int test_field 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)); + void test_method() NO_THREAD_SAFETY_ANALYSIS; }; -class __attribute__((no_thread_safety_analysis)) NoanalTestClass { // \ +class 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))); // \ +void noanal_fun_params(int lvar NO_THREAD_SAFETY_ANALYSIS); // \ // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} @@ -129,30 +129,30 @@ void noanal_fun_params(int lvar __attribute__((no_thread_safety_analysis))); // #error "Should support guarded_var attribute" #endif -int gv_var_noargs __attribute__((guarded_var)); +int gv_var_noargs 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_noargs GUARDED_VAR; int gv_field_args __attribute__((guarded_var(1))); // \ // expected-error {{attribute takes no arguments}} }; -class __attribute__((guarded_var)) GV { // \ +class GUARDED_VAR GV { // \ // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} }; -void gv_function() __attribute__((guarded_var)); // \ +void gv_function() GUARDED_VAR; // \ // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} -void gv_function_params(int gv_lvar __attribute__((guarded_var))); // \ +void gv_function_params(int gv_lvar 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; // \ + int x GUARDED_VAR = y; // \ // expected-warning {{'guarded_var' attribute only applies to fields and global variables}} return x; } @@ -167,21 +167,21 @@ int gv_testfn(int y){ #error "Should support pt_guarded_var attribute" #endif -int *pgv_pt_var_noargs __attribute__((pt_guarded_var)); +int *pgv_pt_var_noargs PT_GUARDED_VAR; -int pgv_var_noargs __attribute__((pt_guarded_var)); // \ +int pgv_var_noargs 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)); // \ + int *pt_field_noargs PT_GUARDED_VAR; + int field_noargs 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 { // \ +class PT_GUARDED_VAR PGV { // \ // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} }; @@ -189,14 +189,14 @@ int *pgv_var_args __attribute__((pt_guarded_var(1))); // \ // expected-error {{attribute takes no arguments}} -void pgv_function() __attribute__((pt_guarded_var)); // \ +void pgv_function() 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))); // \ +void pgv_function_params(int *gv_lvar 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); // \ + int *x PT_GUARDED_VAR = new int(0); // \ // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} delete x; } @@ -211,35 +211,35 @@ void pgv_testfn(int y){ #error "Should support lockable attribute" #endif -class __attribute__((lockable)) LTestClass { +class LOCKABLE LTestClass { }; class __attribute__((lockable (1))) LTestClass_args { // \ // expected-error {{attribute takes no arguments}} }; -void l_test_function() __attribute__((lockable)); // \ +void l_test_function() LOCKABLE; // \ // expected-warning {{'lockable' attribute only applies to classes}} int l_testfn(int y) { - int x __attribute__((lockable)) = y; // \ + int x LOCKABLE = y; // \ // expected-warning {{'lockable' attribute only applies to classes}} return x; } -int l_test_var __attribute__((lockable)); // \ +int l_test_var LOCKABLE; // \ // expected-warning {{'lockable' attribute only applies to classes}} class LFoo { private: - int test_field __attribute__((lockable)); // \ + int test_field LOCKABLE; // \ // expected-warning {{'lockable' attribute only applies to classes}} - void test_method() __attribute__((lockable)); // \ + void test_method() LOCKABLE; // \ // expected-warning {{'lockable' attribute only applies to classes}} }; -void l_function_params(int lvar __attribute__((lockable))); // \ +void l_function_params(int lvar LOCKABLE); // \ // expected-warning {{'lockable' attribute only applies to classes}} @@ -251,35 +251,35 @@ void l_function_params(int lvar __attribute__((lockable))); // \ #error "Should support scoped_lockable attribute" #endif -class __attribute__((scoped_lockable)) SLTestClass { +class SCOPED_LOCKABLE SLTestClass { }; class __attribute__((scoped_lockable (1))) SLTestClass_args { // \ // expected-error {{attribute takes no arguments}} }; -void sl_test_function() __attribute__((scoped_lockable)); // \ +void sl_test_function() SCOPED_LOCKABLE; // \ // expected-warning {{'scoped_lockable' attribute only applies to classes}} int sl_testfn(int y) { - int x __attribute__((scoped_lockable)) = y; // \ + int x SCOPED_LOCKABLE = y; // \ // expected-warning {{'scoped_lockable' attribute only applies to classes}} return x; } -int sl_test_var __attribute__((scoped_lockable)); // \ +int sl_test_var SCOPED_LOCKABLE; // \ // expected-warning {{'scoped_lockable' attribute only applies to classes}} class SLFoo { private: - int test_field __attribute__((scoped_lockable)); // \ + int test_field SCOPED_LOCKABLE; // \ // expected-warning {{'scoped_lockable' attribute only applies to classes}} - void test_method() __attribute__((scoped_lockable)); // \ + void test_method() SCOPED_LOCKABLE; // \ // expected-warning {{'scoped_lockable' attribute only applies to classes}} }; -void sl_function_params(int lvar __attribute__((scoped_lockable))); // \ +void sl_function_params(int lvar SCOPED_LOCKABLE); // \ // expected-warning {{'scoped_lockable' attribute only applies to classes}} @@ -295,7 +295,7 @@ void sl_function_params(int lvar __attribute__((scoped_lockable))); // \ //1. Check applied to the right types & argument number -int gb_var_arg __attribute__((guarded_by(mu1))); +int gb_var_arg GUARDED_BY(mu1); int gb_var_args __attribute__((guarded_by(mu1, mu2))); // \ // expected-error {{attribute takes one argument}} @@ -307,21 +307,21 @@ class GBFoo { private: int gb_field_noargs __attribute__((guarded_by)); // \ // expected-error {{attribute takes one argument}} - int gb_field_args __attribute__((guarded_by(mu1))); + int gb_field_args GUARDED_BY(mu1); }; -class __attribute__((guarded_by(mu1))) GB { // \ +class GUARDED_BY(mu1) GB { // \ // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} }; -void gb_function() __attribute__((guarded_by(mu1))); // \ +void gb_function() 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)))); // \ +void gb_function_params(int gv_lvar 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; // \ + int x GUARDED_BY(mu1) = y; // \ // expected-warning {{'guarded_by' attribute only applies to fields and global variables}} return x; } @@ -329,24 +329,24 @@ int gb_testfn(int y){ //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))); +int gb_var_arg_1 GUARDED_BY(muWrapper.mu); +int gb_var_arg_2 GUARDED_BY(muDoubleWrapper.muWrapper->mu); +int gb_var_arg_3 GUARDED_BY(muWrapper.getMu()); +int gb_var_arg_4 GUARDED_BY(*muWrapper.getMuPointer()); +int gb_var_arg_5 GUARDED_BY(&mu1); +int gb_var_arg_6 GUARDED_BY(muRef); +int gb_var_arg_7 GUARDED_BY(muDoubleWrapper.getWrapper()->getMu()); +int gb_var_arg_8 GUARDED_BY(muPointer); // illegal attribute arguments -int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \ +int gb_var_arg_bad_1 GUARDED_BY(1); // \ // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}} -int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \ - // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}} -int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \ - // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}} -int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \ +int gb_var_arg_bad_2 GUARDED_BY("mu"); // \ + // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} +int gb_var_arg_bad_3 GUARDED_BY(muDoublePointer); // \ + // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mutex **'}} +int gb_var_arg_bad_4 GUARDED_BY(umu); // \ // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}} //3. @@ -366,33 +366,33 @@ int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \ 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_arg PT_GUARDED_BY(mu1); -int *pgb_ptr_var_args __attribute__((guarded_by(mu1, mu2))); // \ +int *pgb_ptr_var_args __attribute__((pt_guarded_by(mu1, mu2))); // \ // expected-error {{attribute takes one argument}} -int pgb_var_args __attribute__((pt_guarded_by(mu1))); // \ +int pgb_var_args 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))); + int *pgb_field_args PT_GUARDED_BY(mu1); }; -class __attribute__((pt_guarded_by(mu1))) PGB { // \ +class 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))); // \ +void pgb_function() 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)))); // \ +void pgb_function_params(int gv_lvar 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); // \ + int *x PT_GUARDED_BY(mu1) = new int(0); // \ // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} delete x; } @@ -400,24 +400,24 @@ void pgb_testfn(int y){ //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))); +int * pgb_var_arg_1 PT_GUARDED_BY(muWrapper.mu); +int * pgb_var_arg_2 PT_GUARDED_BY(muDoubleWrapper.muWrapper->mu); +int * pgb_var_arg_3 PT_GUARDED_BY(muWrapper.getMu()); +int * pgb_var_arg_4 PT_GUARDED_BY(*muWrapper.getMuPointer()); +int * pgb_var_arg_5 PT_GUARDED_BY(&mu1); +int * pgb_var_arg_6 PT_GUARDED_BY(muRef); +int * pgb_var_arg_7 PT_GUARDED_BY(muDoubleWrapper.getWrapper()->getMu()); +int * pgb_var_arg_8 PT_GUARDED_BY(muPointer); // illegal attribute arguments -int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \ +int * pgb_var_arg_bad_1 PT_GUARDED_BY(1); // \ // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} -int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \ +int * pgb_var_arg_bad_2 PT_GUARDED_BY("mu"); // \ + // expected-warning {{ignoring 'pt_guarded_by' attribute because its argument is invalid}} +int * pgb_var_arg_bad_3 PT_GUARDED_BY(muDoublePointer); // \ // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} -int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \ - // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} -int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \ +int * pgb_var_arg_bad_4 PT_GUARDED_BY(umu); // \ // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -431,56 +431,56 @@ int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \ #error "Should support acquired_after attribute" #endif -Mu mu_aa __attribute__((acquired_after(mu1))); +Mutex mu_aa ACQUIRED_AFTER(mu1); -Mu aa_var_noargs __attribute__((acquired_after)); // \ +Mutex aa_var_noargs __attribute__((acquired_after)); // \ // expected-error {{attribute takes at least 1 argument}} class AAFoo { private: - Mu aa_field_noargs __attribute__((acquired_after)); // \ + Mutex aa_field_noargs __attribute__((acquired_after)); // \ // expected-error {{attribute takes at least 1 argument}} - Mu aa_field_args __attribute__((acquired_after(mu1))); + Mutex aa_field_args ACQUIRED_AFTER(mu1); }; -class __attribute__((acquired_after(mu1))) AA { // \ +class ACQUIRED_AFTER(mu1) AA { // \ // expected-warning {{'acquired_after' attribute only applies to fields and global variables}} }; -void aa_function() __attribute__((acquired_after(mu1))); // \ +void aa_function() 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)))); // \ +void aa_function_params(int gv_lvar 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(); // \ + Mutex x ACQUIRED_AFTER(mu1) = Mutex(); // \ // 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))); +Mutex aa_var_arg_1 ACQUIRED_AFTER(muWrapper.mu); +Mutex aa_var_arg_2 ACQUIRED_AFTER(muDoubleWrapper.muWrapper->mu); +Mutex aa_var_arg_3 ACQUIRED_AFTER(muWrapper.getMu()); +Mutex aa_var_arg_4 ACQUIRED_AFTER(*muWrapper.getMuPointer()); +Mutex aa_var_arg_5 ACQUIRED_AFTER(&mu1); +Mutex aa_var_arg_6 ACQUIRED_AFTER(muRef); +Mutex aa_var_arg_7 ACQUIRED_AFTER(muDoubleWrapper.getWrapper()->getMu()); +Mutex aa_var_arg_8 ACQUIRED_AFTER(muPointer); // illegal attribute arguments -Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \ - // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} -Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \ +Mutex aa_var_arg_bad_1 ACQUIRED_AFTER(1); // \ // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} -Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \ +Mutex aa_var_arg_bad_2 ACQUIRED_AFTER("mu"); // \ + // expected-warning {{ignoring 'acquired_after' attribute because its argument is invalid}} +Mutex aa_var_arg_bad_3 ACQUIRED_AFTER(muDoublePointer); // \ // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} -Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \ +Mutex aa_var_arg_bad_4 ACQUIRED_AFTER(umu); // \ // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} -UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \ +UnlockableMu aa_var_arg_bad_5 ACQUIRED_AFTER(mu_aa); // \ // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}} //-----------------------------------------// @@ -491,59 +491,59 @@ UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \ #error "Should support acquired_before attribute" #endif -Mu mu_ab __attribute__((acquired_before(mu1))); +Mutex mu_ab ACQUIRED_BEFORE(mu1); -Mu ab_var_noargs __attribute__((acquired_before)); // \ +Mutex ab_var_noargs __attribute__((acquired_before)); // \ // expected-error {{attribute takes at least 1 argument}} class ABFoo { private: - Mu ab_field_noargs __attribute__((acquired_before)); // \ + Mutex ab_field_noargs __attribute__((acquired_before)); // \ // expected-error {{attribute takes at least 1 argument}} - Mu ab_field_args __attribute__((acquired_before(mu1))); + Mutex ab_field_args ACQUIRED_BEFORE(mu1); }; -class __attribute__((acquired_before(mu1))) AB { // \ +class ACQUIRED_BEFORE(mu1) AB { // \ // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} }; -void ab_function() __attribute__((acquired_before(mu1))); // \ +void ab_function() 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)))); // \ +void ab_function_params(int gv_lvar 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(); // \ + Mutex x ACQUIRED_BEFORE(mu1) = Mutex(); // \ // expected-warning {{'acquired_before' attribute only applies to fields and global variables}} } -// Note: illegal int ab_int __attribute__((acquired_before(mu1))) will +// Note: illegal int ab_int 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))); +Mutex ab_var_arg_1 ACQUIRED_BEFORE(muWrapper.mu); +Mutex ab_var_arg_2 ACQUIRED_BEFORE(muDoubleWrapper.muWrapper->mu); +Mutex ab_var_arg_3 ACQUIRED_BEFORE(muWrapper.getMu()); +Mutex ab_var_arg_4 ACQUIRED_BEFORE(*muWrapper.getMuPointer()); +Mutex ab_var_arg_5 ACQUIRED_BEFORE(&mu1); +Mutex ab_var_arg_6 ACQUIRED_BEFORE(muRef); +Mutex ab_var_arg_7 ACQUIRED_BEFORE(muDoubleWrapper.getWrapper()->getMu()); +Mutex ab_var_arg_8 ACQUIRED_BEFORE(muPointer); // illegal attribute arguments -Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \ +Mutex ab_var_arg_bad_1 ACQUIRED_BEFORE(1); // \ // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} -Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \ +Mutex ab_var_arg_bad_2 ACQUIRED_BEFORE("mu"); // \ + // expected-warning {{ignoring 'acquired_before' attribute because its argument is invalid}} +Mutex ab_var_arg_bad_3 ACQUIRED_BEFORE(muDoublePointer); // \ // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} -Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \ - // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} -Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \ +Mutex ab_var_arg_bad_4 ACQUIRED_BEFORE(umu); // \ // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} -UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \ +UnlockableMu ab_var_arg_bad_5 ACQUIRED_BEFORE(mu_ab); // \ // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}} @@ -557,65 +557,65 @@ UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \ // takes zero or more arguments, all locks (vars/fields) -void elf_function() __attribute__((exclusive_lock_function)); +void elf_function() EXCLUSIVE_LOCK_FUNCTION(); -void elf_function_args() __attribute__((exclusive_lock_function(mu1, mu2))); +void elf_function_args() EXCLUSIVE_LOCK_FUNCTION(mu1, mu2); -int elf_testfn(int y) __attribute__((exclusive_lock_function)); +int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); int elf_testfn(int y) { - int x __attribute__((exclusive_lock_function)) = y; // \ + int x 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)); // \ +int elf_test_var 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)); // \ + int test_field EXCLUSIVE_LOCK_FUNCTION(); // \ // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} - void test_method() __attribute__((exclusive_lock_function)); + void test_method() EXCLUSIVE_LOCK_FUNCTION(); }; -class __attribute__((exclusive_lock_function)) ElfTestClass { // \ +class 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))); // \ +void elf_fun_params(int lvar 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))); +int elf_function_1() EXCLUSIVE_LOCK_FUNCTION(muWrapper.mu); +int elf_function_2() EXCLUSIVE_LOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); +int elf_function_3() EXCLUSIVE_LOCK_FUNCTION(muWrapper.getMu()); +int elf_function_4() EXCLUSIVE_LOCK_FUNCTION(*muWrapper.getMuPointer()); +int elf_function_5() EXCLUSIVE_LOCK_FUNCTION(&mu1); +int elf_function_6() EXCLUSIVE_LOCK_FUNCTION(muRef); +int elf_function_7() EXCLUSIVE_LOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); +int elf_function_8() EXCLUSIVE_LOCK_FUNCTION(muPointer); +int elf_function_9(Mutex x) EXCLUSIVE_LOCK_FUNCTION(1); +int elf_function_9(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(1,2); // illegal attribute arguments -int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \ - // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} -int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \ +int elf_function_bad_2() EXCLUSIVE_LOCK_FUNCTION("mu"); // \ + // expected-warning {{ignoring 'exclusive_lock_function' attribute because its argument is invalid}} +int elf_function_bad_3() EXCLUSIVE_LOCK_FUNCTION(muDoublePointer); // \ // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} -int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \ +int elf_function_bad_4() EXCLUSIVE_LOCK_FUNCTION(umu); // \ // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} -int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \ +int elf_function_bad_1() 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))); // \ +int elf_function_bad_5(Mutex x) 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))); // \ +int elf_function_bad_6(Mutex x, Mutex y) 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))); // \ +int elf_function_bad_7() EXCLUSIVE_LOCK_FUNCTION(0); // \ // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -629,65 +629,65 @@ int elf_function_bad_7() __attribute__((exclusive_lock_function(0))); // \ // takes zero or more arguments, all locks (vars/fields) -void slf_function() __attribute__((shared_lock_function)); +void slf_function() SHARED_LOCK_FUNCTION(); -void slf_function_args() __attribute__((shared_lock_function(mu1, mu2))); +void slf_function_args() SHARED_LOCK_FUNCTION(mu1, mu2); -int slf_testfn(int y) __attribute__((shared_lock_function)); +int slf_testfn(int y) SHARED_LOCK_FUNCTION(); int slf_testfn(int y) { - int x __attribute__((shared_lock_function)) = y; // \ + int x 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)); // \ +int slf_test_var 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))); // \ +void slf_fun_params(int lvar 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)); // \ + int test_field SHARED_LOCK_FUNCTION(); // \ // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} - void test_method() __attribute__((shared_lock_function)); + void test_method() SHARED_LOCK_FUNCTION(); }; -class __attribute__((shared_lock_function)) SlfTestClass { // \ +class 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))); +int slf_function_1() SHARED_LOCK_FUNCTION(muWrapper.mu); +int slf_function_2() SHARED_LOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); +int slf_function_3() SHARED_LOCK_FUNCTION(muWrapper.getMu()); +int slf_function_4() SHARED_LOCK_FUNCTION(*muWrapper.getMuPointer()); +int slf_function_5() SHARED_LOCK_FUNCTION(&mu1); +int slf_function_6() SHARED_LOCK_FUNCTION(muRef); +int slf_function_7() SHARED_LOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); +int slf_function_8() SHARED_LOCK_FUNCTION(muPointer); +int slf_function_9(Mutex x) SHARED_LOCK_FUNCTION(1); +int slf_function_9(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(1,2); // illegal attribute arguments -int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \ +int slf_function_bad_2() SHARED_LOCK_FUNCTION("mu"); // \ + // expected-warning {{ignoring 'shared_lock_function' attribute because its argument is invalid}} +int slf_function_bad_3() SHARED_LOCK_FUNCTION(muDoublePointer); // \ // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} -int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \ - // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} -int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \ +int slf_function_bad_4() SHARED_LOCK_FUNCTION(umu); // \ // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} -int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \ +int slf_function_bad_1() 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))); // \ +int slf_function_bad_5(Mutex x) 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))); // \ +int slf_function_bad_6(Mutex x, Mutex y) 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))); // \ +int slf_function_bad_7() SHARED_LOCK_FUNCTION(0); // \ // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -705,62 +705,62 @@ int slf_function_bad_7() __attribute__((shared_lock_function(0))); // \ void etf_function() __attribute__((exclusive_trylock_function)); // \ // expected-error {{attribute takes at least 1 argument}} -void etf_function_args() __attribute__((exclusive_trylock_function(1, mu2))); +void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2); -void etf_function_arg() __attribute__((exclusive_trylock_function(1))); +void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); -int etf_testfn(int y) __attribute__((exclusive_trylock_function(1))); +int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); int etf_testfn(int y) { - int x __attribute__((exclusive_trylock_function(1))) = y; // \ + int x 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))); // \ +int etf_test_var 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))); // \ + int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} - void test_method() __attribute__((exclusive_trylock_function(1))); + void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); }; -class __attribute__((exclusive_trylock_function(1))) EtfTestClass { // \ +class 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)))); // \ +void etf_fun_params(int lvar 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))); +int etf_function_1() EXCLUSIVE_TRYLOCK_FUNCTION(1, muWrapper.mu); +int etf_function_2() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.muWrapper->mu); +int etf_function_3() EXCLUSIVE_TRYLOCK_FUNCTION(1, muWrapper.getMu()); +int etf_function_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, *muWrapper.getMuPointer()); +int etf_function_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, &mu1); +int etf_function_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, muRef); +int etf_function_7() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); +int etf_functetfn_8() EXCLUSIVE_TRYLOCK_FUNCTION(1, muPointer); +int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); // illegal attribute arguments -int etf_function_bad_1() __attribute__((exclusive_trylock_function(mu1))); // \ +int etf_function_bad_1() 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"))); // \ +int etf_function_bad_2() 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))); // \ +int etf_function_bad_3() EXCLUSIVE_TRYLOCK_FUNCTION(muDoublePointer); // \ // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} -int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \ - // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} -int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \ +int etf_function_bad_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, "mu"); // \ + // expected-warning {{ignoring 'exclusive_trylock_function' attribute because its argument is invalid}} +int etf_function_bad_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoublePointer); // \ // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} -int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \ +int etf_function_bad_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, umu); // \ // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -778,63 +778,63 @@ int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // 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_args() SHARED_TRYLOCK_FUNCTION(1, mu2); -void stf_function_arg() __attribute__((shared_trylock_function(1))); +void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); -int stf_testfn(int y) __attribute__((shared_trylock_function(1))); +int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); int stf_testfn(int y) { - int x __attribute__((shared_trylock_function(1))) = y; // \ + int x 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))); // \ +int stf_test_var 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)))); // \ +void stf_fun_params(int lvar 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))); // \ + int test_field SHARED_TRYLOCK_FUNCTION(1); // \ // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} - void test_method() __attribute__((shared_trylock_function(1))); + void test_method() SHARED_TRYLOCK_FUNCTION(1); }; -class __attribute__((shared_trylock_function(1))) StfTestClass { // \ +class 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))); +int stf_function_1() SHARED_TRYLOCK_FUNCTION(1, muWrapper.mu); +int stf_function_2() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.muWrapper->mu); +int stf_function_3() SHARED_TRYLOCK_FUNCTION(1, muWrapper.getMu()); +int stf_function_4() SHARED_TRYLOCK_FUNCTION(1, *muWrapper.getMuPointer()); +int stf_function_5() SHARED_TRYLOCK_FUNCTION(1, &mu1); +int stf_function_6() SHARED_TRYLOCK_FUNCTION(1, muRef); +int stf_function_7() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); +int stf_function_8() SHARED_TRYLOCK_FUNCTION(1, muPointer); +int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); // illegal attribute arguments -int stf_function_bad_1() __attribute__((shared_trylock_function(mu1))); // \ +int stf_function_bad_1() 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"))); // \ +int stf_function_bad_2() 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))); // \ +int stf_function_bad_3() 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"))); // \ +int stf_function_bad_4() SHARED_TRYLOCK_FUNCTION(1, "mu"); // \ + // expected-warning {{ignoring 'shared_trylock_function' attribute because its argument is invalid}} +int stf_function_bad_5() SHARED_TRYLOCK_FUNCTION(1, muDoublePointer); // \ // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} -int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \ - // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} -int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \ +int stf_function_bad_6() SHARED_TRYLOCK_FUNCTION(1, umu); // \ // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -848,65 +848,65 @@ int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \ // takes zero or more arguments, all locks (vars/fields) -void uf_function() __attribute__((unlock_function)); +void uf_function() UNLOCK_FUNCTION(); -void uf_function_args() __attribute__((unlock_function(mu1, mu2))); +void uf_function_args() UNLOCK_FUNCTION(mu1, mu2); -int uf_testfn(int y) __attribute__((unlock_function)); +int uf_testfn(int y) UNLOCK_FUNCTION(); int uf_testfn(int y) { - int x __attribute__((unlock_function)) = y; // \ + int x UNLOCK_FUNCTION() = y; // \ // expected-warning {{'unlock_function' attribute only applies to functions and methods}} return x; }; -int uf_test_var __attribute__((unlock_function)); // \ +int uf_test_var UNLOCK_FUNCTION(); // \ // expected-warning {{'unlock_function' attribute only applies to functions and methods}} class UfFoo { private: - int test_field __attribute__((unlock_function)); // \ + int test_field UNLOCK_FUNCTION(); // \ // expected-warning {{'unlock_function' attribute only applies to functions and methods}} - void test_method() __attribute__((unlock_function)); + void test_method() UNLOCK_FUNCTION(); }; -class __attribute__((no_thread_safety_analysis)) UfTestClass { // \ +class 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))); // \ +void uf_fun_params(int lvar 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))); +int uf_function_1() UNLOCK_FUNCTION(muWrapper.mu); +int uf_function_2() UNLOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); +int uf_function_3() UNLOCK_FUNCTION(muWrapper.getMu()); +int uf_function_4() UNLOCK_FUNCTION(*muWrapper.getMuPointer()); +int uf_function_5() UNLOCK_FUNCTION(&mu1); +int uf_function_6() UNLOCK_FUNCTION(muRef); +int uf_function_7() UNLOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); +int uf_function_8() UNLOCK_FUNCTION(muPointer); +int uf_function_9(Mutex x) UNLOCK_FUNCTION(1); +int uf_function_9(Mutex x, Mutex y) UNLOCK_FUNCTION(1,2); // illegal attribute arguments -int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \ - // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} -int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \ +int uf_function_bad_2() UNLOCK_FUNCTION("mu"); // \ + // expected-warning {{ignoring 'unlock_function' attribute because its argument is invalid}} +int uf_function_bad_3() UNLOCK_FUNCTION(muDoublePointer); // \ // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} -int uf_function_bad_4() __attribute__((unlock_function(umu))); // \ +int uf_function_bad_4() UNLOCK_FUNCTION(umu); // \ // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} -int uf_function_bad_1() __attribute__((unlock_function(1))); // \ +int uf_function_bad_1() 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))); // \ +int uf_function_bad_5(Mutex x) 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))); // \ +int uf_function_bad_6(Mutex x, Mutex y) 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))); // \ +int uf_function_bad_7() UNLOCK_FUNCTION(0); // \ // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -923,57 +923,57 @@ int uf_function_bad_7() __attribute__((unlock_function(0))); // \ void lr_function() __attribute__((lock_returned)); // \ // expected-error {{attribute takes one argument}} -void lr_function_arg() __attribute__((lock_returned(mu1))); +void lr_function_arg() 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) LOCK_RETURNED(mu1); int lr_testfn(int y) { - int x __attribute__((lock_returned(mu1))) = y; // \ + int x 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))); // \ +int lr_test_var LOCK_RETURNED(mu1); // \ // expected-warning {{'lock_returned' attribute only applies to functions and methods}} -void lr_fun_params(int lvar __attribute__((lock_returned(mu1)))); // \ +void lr_fun_params(int lvar LOCK_RETURNED(mu1)); // \ // expected-warning {{'lock_returned' attribute only applies to functions and methods}} class LrFoo { private: - int test_field __attribute__((lock_returned(mu1))); // \ + int test_field LOCK_RETURNED(mu1); // \ // expected-warning {{'lock_returned' attribute only applies to functions and methods}} - void test_method() __attribute__((lock_returned(mu1))); + void test_method() LOCK_RETURNED(mu1); }; -class __attribute__((lock_returned(mu1))) LrTestClass { // \ +class 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))); +int lr_function_1() LOCK_RETURNED(muWrapper.mu); +int lr_function_2() LOCK_RETURNED(muDoubleWrapper.muWrapper->mu); +int lr_function_3() LOCK_RETURNED(muWrapper.getMu()); +int lr_function_4() LOCK_RETURNED(*muWrapper.getMuPointer()); +int lr_function_5() LOCK_RETURNED(&mu1); +int lr_function_6() LOCK_RETURNED(muRef); +int lr_function_7() LOCK_RETURNED(muDoubleWrapper.getWrapper()->getMu()); +int lr_function_8() LOCK_RETURNED(muPointer); // illegal attribute arguments -int lr_function_bad_1() __attribute__((lock_returned(1))); // \ +int lr_function_bad_1() LOCK_RETURNED(1); // \ // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} -int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \ +int lr_function_bad_2() LOCK_RETURNED("mu"); // \ + // expected-warning {{ignoring 'lock_returned' attribute because its argument is invalid}} +int lr_function_bad_3() LOCK_RETURNED(muDoublePointer); // \ // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} -int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \ - // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} -int lr_function_bad_4() __attribute__((lock_returned(umu))); // \ +int lr_function_bad_4() LOCK_RETURNED(umu); // \ // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -991,56 +991,56 @@ int lr_function_bad_4() __attribute__((lock_returned(umu))); // \ 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_arg() LOCKS_EXCLUDED(mu1); -void le_function_args() __attribute__((locks_excluded(mu1, mu2))); +void le_function_args() LOCKS_EXCLUDED(mu1, mu2); -int le_testfn(int y) __attribute__((locks_excluded(mu1))); +int le_testfn(int y) LOCKS_EXCLUDED(mu1); int le_testfn(int y) { - int x __attribute__((locks_excluded(mu1))) = y; // \ + int x 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))); // \ +int le_test_var LOCKS_EXCLUDED(mu1); // \ // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} -void le_fun_params(int lvar __attribute__((locks_excluded(mu1)))); // \ +void le_fun_params(int lvar LOCKS_EXCLUDED(mu1)); // \ // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} class LeFoo { private: - int test_field __attribute__((locks_excluded(mu1))); // \ + int test_field LOCKS_EXCLUDED(mu1); // \ // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} - void test_method() __attribute__((locks_excluded(mu1))); + void test_method() LOCKS_EXCLUDED(mu1); }; -class __attribute__((locks_excluded(mu1))) LeTestClass { // \ +class 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))); +int le_function_1() LOCKS_EXCLUDED(muWrapper.mu); +int le_function_2() LOCKS_EXCLUDED(muDoubleWrapper.muWrapper->mu); +int le_function_3() LOCKS_EXCLUDED(muWrapper.getMu()); +int le_function_4() LOCKS_EXCLUDED(*muWrapper.getMuPointer()); +int le_function_5() LOCKS_EXCLUDED(&mu1); +int le_function_6() LOCKS_EXCLUDED(muRef); +int le_function_7() LOCKS_EXCLUDED(muDoubleWrapper.getWrapper()->getMu()); +int le_function_8() LOCKS_EXCLUDED(muPointer); // illegal attribute arguments -int le_function_bad_1() __attribute__((locks_excluded(1))); // \ - // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} -int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \ +int le_function_bad_1() LOCKS_EXCLUDED(1); // \ // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} -int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \ +int le_function_bad_2() LOCKS_EXCLUDED("mu"); // \ + // expected-warning {{ignoring 'locks_excluded' attribute because its argument is invalid}} +int le_function_bad_3() LOCKS_EXCLUDED(muDoublePointer); // \ // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} -int le_function_bad_4() __attribute__((locks_excluded(umu))); // \ +int le_function_bad_4() LOCKS_EXCLUDED(umu); // \ // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -1058,56 +1058,56 @@ int le_function_bad_4() __attribute__((locks_excluded(umu))); // \ 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_arg() EXCLUSIVE_LOCKS_REQUIRED(mu1); -void elr_function_args() __attribute__((exclusive_locks_required(mu1, mu2))); +void elr_function_args() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2); -int elr_testfn(int y) __attribute__((exclusive_locks_required(mu1))); +int elr_testfn(int y) EXCLUSIVE_LOCKS_REQUIRED(mu1); int elr_testfn(int y) { - int x __attribute__((exclusive_locks_required(mu1))) = y; // \ + int x 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))); // \ +int elr_test_var 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)))); // \ +void elr_fun_params(int lvar 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))); // \ + int test_field EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} - void test_method() __attribute__((exclusive_locks_required(mu1))); + void test_method() EXCLUSIVE_LOCKS_REQUIRED(mu1); }; -class __attribute__((exclusive_locks_required(mu1))) ElrTestClass { // \ +class 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))); +int elr_function_1() EXCLUSIVE_LOCKS_REQUIRED(muWrapper.mu); +int elr_function_2() EXCLUSIVE_LOCKS_REQUIRED(muDoubleWrapper.muWrapper->mu); +int elr_function_3() EXCLUSIVE_LOCKS_REQUIRED(muWrapper.getMu()); +int elr_function_4() EXCLUSIVE_LOCKS_REQUIRED(*muWrapper.getMuPointer()); +int elr_function_5() EXCLUSIVE_LOCKS_REQUIRED(&mu1); +int elr_function_6() EXCLUSIVE_LOCKS_REQUIRED(muRef); +int elr_function_7() EXCLUSIVE_LOCKS_REQUIRED(muDoubleWrapper.getWrapper()->getMu()); +int elr_function_8() EXCLUSIVE_LOCKS_REQUIRED(muPointer); // illegal attribute arguments -int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \ +int elr_function_bad_1() EXCLUSIVE_LOCKS_REQUIRED(1); // \ // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} -int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \ +int elr_function_bad_2() EXCLUSIVE_LOCKS_REQUIRED("mu"); // \ + // expected-warning {{ignoring 'exclusive_locks_required' attribute because its argument is invalid}} +int elr_function_bad_3() EXCLUSIVE_LOCKS_REQUIRED(muDoublePointer); // \ // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} -int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \ - // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} -int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \ +int elr_function_bad_4() EXCLUSIVE_LOCKS_REQUIRED(umu); // \ // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -1126,56 +1126,56 @@ int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \ 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_arg() SHARED_LOCKS_REQUIRED(mu1); -void slr_function_args() __attribute__((shared_locks_required(mu1, mu2))); +void slr_function_args() SHARED_LOCKS_REQUIRED(mu1, mu2); -int slr_testfn(int y) __attribute__((shared_locks_required(mu1))); +int slr_testfn(int y) SHARED_LOCKS_REQUIRED(mu1); int slr_testfn(int y) { - int x __attribute__((shared_locks_required(mu1))) = y; // \ + int x 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))); // \ +int slr_test_var 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)))); // \ +void slr_fun_params(int lvar 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))); // \ + int test_field SHARED_LOCKS_REQUIRED(mu1); // \ // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} - void test_method() __attribute__((shared_locks_required(mu1))); + void test_method() SHARED_LOCKS_REQUIRED(mu1); }; -class __attribute__((shared_locks_required(mu1))) SlrTestClass { // \ +class 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))); +int slr_function_1() SHARED_LOCKS_REQUIRED(muWrapper.mu); +int slr_function_2() SHARED_LOCKS_REQUIRED(muDoubleWrapper.muWrapper->mu); +int slr_function_3() SHARED_LOCKS_REQUIRED(muWrapper.getMu()); +int slr_function_4() SHARED_LOCKS_REQUIRED(*muWrapper.getMuPointer()); +int slr_function_5() SHARED_LOCKS_REQUIRED(&mu1); +int slr_function_6() SHARED_LOCKS_REQUIRED(muRef); +int slr_function_7() SHARED_LOCKS_REQUIRED(muDoubleWrapper.getWrapper()->getMu()); +int slr_function_8() SHARED_LOCKS_REQUIRED(muPointer); // illegal attribute arguments -int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \ - // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} -int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \ +int slr_function_bad_1() SHARED_LOCKS_REQUIRED(1); // \ // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} -int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \ +int slr_function_bad_2() SHARED_LOCKS_REQUIRED("mu"); // \ + // expected-warning {{ignoring 'shared_locks_required' attribute because its argument is invalid}} +int slr_function_bad_3() SHARED_LOCKS_REQUIRED(muDoublePointer); // \ // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} -int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \ +int slr_function_bad_4() SHARED_LOCKS_REQUIRED(umu); // \ // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -1240,43 +1240,43 @@ struct Foomgoper { // Parsing of member variables and function parameters //------------------------------------------------------ -Mu gmu; +Mutex gmu; class StaticMu { - static Mu statmu; + static Mutex 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))); + void foo1() EXCLUSIVE_LOCKS_REQUIRED(gmu) { } + void foo2() EXCLUSIVE_LOCKS_REQUIRED(mu) { } + void foo3(Mutex *m) EXCLUSIVE_LOCKS_REQUIRED(m) { } + void foo3(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu) { } + void foo4(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu); - static void foo5() __attribute__((exclusive_locks_required(mu))); // \ + static void foo5() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ // expected-error {{'this' cannot be implicitly used in a static member function declaration}} template <class T> - void foo6() __attribute__((exclusive_locks_required(T::statmu))) { } + void foo6() EXCLUSIVE_LOCKS_REQUIRED(T::statmu) { } template <class T> - void foo7(T* f) __attribute__((exclusive_locks_required(f->mu))) { } + void foo7(T* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu) { } - int a __attribute__((guarded_by(gmu))); - int b __attribute__((guarded_by(mu))); - int c __attribute__((guarded_by(this->mu))); + int a GUARDED_BY(gmu); + int b GUARDED_BY(mu); + int c GUARDED_BY(this->mu); - Mu mu; + Mutex mu; }; //------------------------- // Empty argument lists //------------------------- -class __attribute__((lockable)) EmptyArgListsTest { - void lock() __attribute__((exclusive_lock_function())) { } - void unlock() __attribute__((unlock_function())) { } +class LOCKABLE EmptyArgListsTest { + void lock() EXCLUSIVE_LOCK_FUNCTION() { } + void unlock() UNLOCK_FUNCTION() { } }; @@ -1285,7 +1285,7 @@ namespace FunctionDefinitionParseTest { class Foo { public: - Mu mu_; + Mutex mu_; void foo1(); void foo2(Foo *f); }; @@ -1293,17 +1293,17 @@ public: template <class T> class Bar { public: - Mu mu_; + Mutex mu_; void bar(); }; -void Foo::foo1() __attribute__((exclusive_locks_required(mu_))) { } -void Foo::foo2(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { } +void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) { } +void Foo::foo2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { } template <class T> -void Bar<T>::bar() __attribute__((exclusive_locks_required(mu_))) { } +void Bar<T>::bar() EXCLUSIVE_LOCKS_REQUIRED(mu_) { } -void baz(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { } +void baz(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { } } // end namespace @@ -1312,13 +1312,15 @@ namespace TestMultiDecl { class Foo { public: - int __attribute__((guarded_by(mu_))) a; - int __attribute__((guarded_by(mu_))) b, c; + int GUARDED_BY(mu_) a; + int GUARDED_BY(mu_) b, c; private: - Mu mu_; + Mutex mu_; }; +} // end namespace TestMultiDecl + namespace NestedClassLateDecl { @@ -1331,15 +1333,100 @@ class Foo { void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu) { b->a = 0; } void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; } - Mu mu; + Mutex mu; }; int a GUARDED_BY(fooMu); - Mu fooMu; - static Mu fooMuStatic; + Mutex fooMu; + static Mutex fooMuStatic; }; } -} // end namespace TestMultiDecl +namespace PointerToMemberTest { + +// Empty string should be ignored. +int testEmptyAttribute GUARDED_BY(""); +void testEmptyAttributeFunction() EXCLUSIVE_LOCKS_REQUIRED(""); + +class Graph { +public: + Mutex mu_; + + static Mutex* get_static_mu() LOCK_RETURNED(&Graph::mu_); +}; + +class Node { +public: + void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_); + int a GUARDED_BY(&Graph::mu_); +}; + +} + + +namespace SmartPointerTest { + +template<class T> +class smart_ptr { + public: + T* operator->() { return ptr_; } + T& operator*() { return ptr_; } + + private: + T* ptr_; +}; + + +Mutex gmu; +smart_ptr<int> gdat PT_GUARDED_BY(gmu); + + +class MyClass { +public: + Mutex mu_; + smart_ptr<Mutex> smu_; + + + smart_ptr<int> a PT_GUARDED_BY(mu_); + int b GUARDED_BY(smu_); +}; + +} + + +namespace InheritanceTest { + +class LOCKABLE Base { + public: + void lock() EXCLUSIVE_LOCK_FUNCTION(); + void unlock() UNLOCK_FUNCTION(); +}; + +class Base2 { }; + +class Derived1 : public Base { }; + +class Derived2 : public Base2, public Derived1 { }; + +class Derived3 : public Base2 { }; + +class Foo { + Derived1 mu1_; + Derived2 mu2_; + Derived3 mu3_; + int a GUARDED_BY(mu1_); + int b GUARDED_BY(mu2_); + int c GUARDED_BY(mu3_); // \ + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class InheritanceTest::Derived3'}} + + void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1_, mu2_) { + a = 0; + b = 0; + } +}; + +} + + diff --git a/test/SemaCXX/warn-unique-enum.cpp b/test/SemaCXX/warn-unique-enum.cpp new file mode 100644 index 000000000000..59a127807172 --- /dev/null +++ b/test/SemaCXX/warn-unique-enum.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wunique-enum +enum A { A1 = 1, A2 = 1, A3 = 1 }; // expected-warning {{all elements of 'A' are initialized with literals to value 1}} \ +// expected-note {{initialize the last element with the previous element to silence this warning}} +enum { B1 = 1, B2 = 1, B3 = 1 }; // no warning +enum C { // expected-warning {{all elements of 'C' are initialized with literals to value 1}} + C1 = true, + C2 = true // expected-note {{initialize the last element with the previous element to silence this warning}} +}; +enum D { D1 = 5, D2 = 5L, D3 = 5UL, D4 = 5LL, D5 = 5ULL }; // expected-warning {{all elements of 'D' are initialized with literals to value 5}} \ +// expected-note {{initialize the last element with the previous element to silence this warning}} + +// Don't warn on enums with less than 2 elements. +enum E { E1 = 4 }; +enum F { F1 }; +enum G {}; + +// Don't warn when integer literals do not initialize the elements. +enum H { H1 = 4, H_MAX = H1, H_MIN = H1 }; +enum I { I1 = H1, I2 = 4 }; +enum J { J1 = 4, J2 = I2 }; +enum K { K1, K2, K3, K4 }; + +// Don't crash or warn on this one. +// rdar://11875995 +enum L { + L1 = 0x8000000000000000ULL, L2 = 0x0000000000000001ULL +}; diff --git a/test/SemaCXX/warn-unused-private-field.cpp b/test/SemaCXX/warn-unused-private-field.cpp new file mode 100644 index 000000000000..661442db9e9d --- /dev/null +++ b/test/SemaCXX/warn-unused-private-field.cpp @@ -0,0 +1,246 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -verify -std=c++11 %s + +class NotFullyDefined { + public: + NotFullyDefined(); + private: + int y; +}; + +class HasUndefinedNestedClass { + class Undefined; + int unused_; +}; + +class HasUndefinedPureVirtualDestructor { + virtual ~HasUndefinedPureVirtualDestructor() = 0; + int unused_; +}; + +class HasDefinedNestedClasses { + class DefinedHere {}; + class DefinedOutside; + int unused_; // expected-warning{{private field 'unused_' is not used}} +}; +class HasDefinedNestedClasses::DefinedOutside {}; + +class HasUndefinedFriendFunction { + friend void undefinedFriendFunction(); + int unused_; +}; + +class HasUndefinedFriendClass { + friend class NotFullyDefined; + friend class NotDefined; + int unused_; +}; + +class HasFriend { + friend class FriendClass; + friend void friendFunction(HasFriend f); + int unused_; // expected-warning{{private field 'unused_' is not used}} + int used_by_friend_class_; + int used_by_friend_function_; +}; + +class ClassWithTemplateFriend { + template <typename T> friend class TemplateFriend; + int used_by_friend_; + int unused_; +}; + +template <typename T> class TemplateFriend { +public: + TemplateFriend(ClassWithTemplateFriend my_friend) { + int var = my_friend.used_by_friend_; + } +}; + +class FriendClass { + HasFriend my_friend_; + void use() { + my_friend_.used_by_friend_class_ = 42; + } +}; + +void friendFunction(HasFriend my_friend) { + my_friend.used_by_friend_function_ = 42; +} + +class NonTrivialConstructor { + public: + NonTrivialConstructor() {} +}; + +class NonTrivialDestructor { + public: + ~NonTrivialDestructor() {} +}; + +class Trivial { + public: + Trivial() = default; + Trivial(int a) {} +}; + +int side_effect() { + return 42; +} + +class A { + public: + A() : primitive_type_(42), default_initializer_(), other_initializer_(42), + trivial_(), user_constructor_(42), + initialized_with_side_effect_(side_effect()) { + used_ = 42; + attr_used_ = 42; // expected-warning{{'attr_used_' was marked unused but was used}} + } + + A(int x, A* a) : pointer_(a) {} + + private: + int primitive_type_; // expected-warning{{private field 'primitive_type_' is not used}} + A* pointer_; // expected-warning{{private field 'pointer_' is not used}} + int no_initializer_; // expected-warning{{private field 'no_initializer_' is not used}} + int default_initializer_; // expected-warning{{private field 'default_initializer_' is not used}} + int other_initializer_; // expected-warning{{private field 'other_initializer_' is not used}} + int used_, unused_; // expected-warning{{private field 'unused_' is not used}} + int in_class_initializer_ = 42; // expected-warning{{private field 'in_class_initializer_' is not used}} + int in_class_initializer_with_side_effect_ = side_effect(); + Trivial trivial_initializer_ = Trivial(); // expected-warning{{private field 'trivial_initializer_' is not used}} + Trivial non_trivial_initializer_ = Trivial(42); + int initialized_with_side_effect_; + static int static_fields_are_ignored_; + + Trivial trivial_; // expected-warning{{private field 'trivial_' is not used}} + Trivial user_constructor_; + NonTrivialConstructor non_trivial_constructor_; + NonTrivialDestructor non_trivial_destructor_; + + int attr_ __attribute__((unused)); + int attr_used_ __attribute__((unused)); +}; + +class EverythingUsed { + public: + EverythingUsed() : as_array_index_(0), var_(by_initializer_) { + var_ = sizeof(sizeof_); + int *use = &by_reference_; + int test[2]; + test[as_array_index_] = 42; + } + + template<class T> + void useStuff(T t) { + by_template_function_ = 42; + } + + private: + int var_; + int sizeof_; + int by_reference_; + int by_template_function_; + int as_array_index_; + int by_initializer_; +}; + +class HasFeatureTest { +#if __has_feature(attribute_unused_on_fields) + int unused_; // expected-warning{{private field 'unused_' is not used}} + int unused2_ __attribute__((unused)); // no-warning +#endif +}; + +namespace templates { +class B { + template <typename T> void f(T t); + int a; +}; +} // namespace templates + +namespace mutual_friends { +// Undefined methods make mutual friends undefined. +class A { + int a; + friend class B; + void doSomethingToAOrB(); +}; +class B { + int b; + friend class A; +}; + +// Undefined friends do not make a mutual friend undefined. +class C { + int c; + void doSomethingElse() {} + friend class E; + friend class D; +}; +class D { + int d; // expected-warning{{private field 'd' is not used}} + friend class C; +}; + +// Undefined nested classes make mutual friends undefined. +class F { + int f; + class G; + friend class H; +}; +class H { + int h; + friend class F; +}; +} // namespace mutual_friends + +namespace anonymous_structs_unions { +class A { + private: + // FIXME: Look at the DeclContext for anonymous structs/unions. + union { + int *Aligner; + unsigned char Data[8]; + }; +}; +union S { + private: + int *Aligner; + unsigned char Data[8]; +}; +} // namespace anonymous_structs_unions + +namespace pr13413 { +class A { + A() : p_(__null), b_(false), a_(this), p2_(nullptr) {} + void* p_; // expected-warning{{private field 'p_' is not used}} + bool b_; // expected-warning{{private field 'b_' is not used}} + A* a_; // expected-warning{{private field 'a_' is not used}} + void* p2_; // expected-warning{{private field 'p2_' is not used}} +}; +} + +namespace pr13543 { + void f(int); + void f(char); + struct S { + S() : p(&f) {} + private: + void (*p)(int); // expected-warning{{private field 'p' is not used}} + }; + + struct A { int n; }; + struct B { + B() : a(A()) {} + B(char) {} + B(int n) : a{n}, b{(f(n), 0)} {} + private: + A a = A(); // expected-warning{{private field 'a' is not used}} + A b; + }; + + struct X { ~X(); }; + class C { + X x[4]; // no-warning + }; +} diff --git a/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp index 1c0263c581c1..072ee60f1f35 100644 --- a/test/SemaCXX/warn-unused-value.cpp +++ b/test/SemaCXX/warn-unused-value.cpp @@ -12,7 +12,7 @@ namespace test0 { // pointer to volatile has side effect (thus no warning) Box* box = new Box; box->i; // expected-warning {{expression result unused}} - box->j; + box->j; // expected-warning {{expression result unused}} } } |