diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
| commit | 9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch) | |
| tree | 47df2c12b57214af6c31e47404b005675b8b7ffc /test/SemaCXX | |
| parent | f73d5f23a889b93d89ddef61ac0995df40286bb8 (diff) | |
Notes
Diffstat (limited to 'test/SemaCXX')
210 files changed, 8594 insertions, 1004 deletions
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp index 05037ac6a0d03..fb7d9751d1a5a 100644 --- a/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -3,6 +3,7 @@ typedef unsigned short char16_t; typedef unsigned int char32_t; +struct _Atomic {}; typename decltype(3) a; // expected-warning {{expected a qualified name after 'typename'}} @@ -21,6 +22,12 @@ void test() } +namespace ms_predefined_types { + // ::type_info is a built-in forward class declaration. + void f(const type_info &a); + void f(size_t); +} + namespace ms_protected_scope { struct C { C(); }; @@ -105,6 +112,9 @@ public: class B : public A { private: using A::f; + void g() { + f(); // no diagnostic + } }; class C : public B { @@ -114,6 +124,27 @@ private: } +namespace using_tag_redeclaration +{ + struct S; + namespace N { + using ::using_tag_redeclaration::S; + struct S {}; // expected-note {{previous definition is here}} + } + void f() { + N::S s1; + S s2; + } + void g() { + struct S; // expected-note {{forward declaration of 'S'}} + S s3; // expected-error {{variable has incomplete type 'S'}} + } + void h() { + using ::using_tag_redeclaration::S; + struct S {}; // expected-error {{redefinition of 'S'}} + } +} + namespace MissingTypename { diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index c5b45a2905c8b..6d221a409e7bc 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -1,10 +1,6 @@ // RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify -fms-extensions -fexceptions -fcxx-exceptions -// ::type_info is predeclared with forward class declartion -void f(const type_info &a); - - // Microsoft doesn't validate exception specification. namespace microsoft_exception_spec { @@ -37,11 +33,11 @@ class B : public A { // MSVC allows type definition in anonymous union and struct struct A { - union + union { int a; struct B // expected-warning {{types declared in an anonymous union are a Microsoft extension}} - { + { int c; } d; @@ -63,7 +59,7 @@ struct A { int c2; } d2; - + union C2 // expected-warning {{types declared in an anonymous struct are a Microsoft extension}} { int e2; @@ -78,7 +74,7 @@ struct A // __stdcall handling struct M { int __stdcall addP(); - float __stdcall subtractP(); + float __stdcall subtractP(); }; // __unaligned handling @@ -90,7 +86,7 @@ template<typename T> void h1(T (__stdcall M::* const )()) { } void m1() { h1<int>(&M::addP); h1(&M::subtractP); -} +} @@ -98,7 +94,7 @@ void m1() { void f(long long); void f(int); - + int main() { // This is an ambiguous call in standard C++. @@ -123,10 +119,11 @@ enum : long long { // expected-warning{{enumeration types with a fixed underlyi class AAA { __declspec(dllimport) void f(void) { } -void f2(void); +void f2(void); // expected-note{{previous declaration is here}} }; -__declspec(dllimport) void AAA::f2(void) { // expected-error {{dllimport attribute can be applied only to symbol}} +__declspec(dllimport) void AAA::f2(void) { // expected-error{{dllimport cannot be applied to non-inline function definition}} + // expected-error@-1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}} } @@ -147,11 +144,14 @@ extern void static_func(); void static_func(); // expected-note {{previous declaration is here}} -static void static_func() // expected-warning {{static declaration of 'static_func' follows non-static declaration}} +static void static_func() // expected-warning {{redeclaring non-static 'static_func' as static is a Microsoft extension}} { } +extern const int static_var; // expected-note {{previous declaration is here}} +static const int static_var = 3; // expected-warning {{redeclaring non-static 'static_var' as static is a Microsoft extension}} + long function_prototype(int a); long (*function_ptr)(int a); @@ -176,29 +176,6 @@ void pointer_to_integral_type_conv(char* ptr) { b = reinterpret_cast<bool>(ptr); // expected-error {{cast from pointer to smaller type 'bool' loses information}} } -namespace friend_as_a_forward_decl { - -class A { - class Nested { - friend class B; - B* b; - }; - B* b; -}; -B* global_b; - - -void f() -{ - class Local { - friend class Z; - Z* b; - }; - Z* b; -} - -} - struct PR11150 { class X { virtual void f() = 0; @@ -307,7 +284,7 @@ struct SP9 { __declspec(property(get=GetV, put=SetV)) T V; T GetV() { return 0; } void SetV(T v) {} - void f() { V = this->V; V < this->V; } + bool f() { V = this->V; return V < this->V; } void g() { V++; } void h() { V*=2; } }; @@ -368,18 +345,18 @@ struct StructWithUnnamedMember { namespace rdar14250378 { class Bar {}; - + namespace NyNamespace { class Foo { public: Bar* EnsureBar(); }; - + class Baz : public Foo { public: friend class Bar; }; - + Bar* Foo::EnsureBar() { return 0; } @@ -410,3 +387,14 @@ struct SealedType sealed : SomeBase { // expected-error@+1 {{base 'SealedType' is marked 'sealed'}} struct InheritFromSealed : SealedType {}; + +void AfterClassBody() { + // expected-warning@+1 {{attribute 'deprecated' is ignored, place it after "struct" to apply attribute to type declaration}} + struct D {} __declspec(deprecated); + + struct __declspec(align(4)) S {} __declspec(align(8)) s1; + S s2; + _Static_assert(__alignof(S) == 4, ""); + _Static_assert(__alignof(s1) == 8, ""); + _Static_assert(__alignof(s2) == 4, ""); +} diff --git a/test/SemaCXX/PR19955.cpp b/test/SemaCXX/PR19955.cpp new file mode 100644 index 0000000000000..cbbe2fe9af164 --- /dev/null +++ b/test/SemaCXX/PR19955.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple i686-win32 -verify -std=c++11 %s +// RUN: %clang_cc1 -triple i686-mingw32 -verify -std=c++11 %s + +extern int __attribute__((dllimport)) var; +constexpr int *varp = &var; // expected-error {{must be initialized by a constant expression}} + +extern __attribute__((dllimport)) void fun(); +constexpr void (*funp)(void) = &fun; // expected-error {{must be initialized by a constant expression}} + +template <void (*)()> +struct S {}; +S<&fun> x; + +template <int *> +struct U {}; +U<&var> y; diff --git a/test/SemaCXX/PR20110.cpp b/test/SemaCXX/PR20110.cpp new file mode 100644 index 0000000000000..e540a738b87b6 --- /dev/null +++ b/test/SemaCXX/PR20110.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// expected-no-diagnostics + +// FIXME: These templates should trigger errors in C++11 mode. + +template <char const *p> +class A { + char const *get_p() { return *p; } +}; +template <int p> +class B { + char const *get_p() { return p; } +}; + diff --git a/test/SemaCXX/PR8012.cpp b/test/SemaCXX/PR8012.cpp index 9cfc2b000c014..0a43af7c297cd 100644 --- a/test/SemaCXX/PR8012.cpp +++ b/test/SemaCXX/PR8012.cpp @@ -1,3 +1,3 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -void foo (int operator+); // expected-error{{cannot be the name of a parameter}} +void foo(int operator+); // expected-error{{'operator+' cannot be the name of a parameter}} diff --git a/test/SemaCXX/__try.cpp b/test/SemaCXX/__try.cpp index 1c45581b32f9d..28a3701488785 100644 --- a/test/SemaCXX/__try.cpp +++ b/test/SemaCXX/__try.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fborland-extensions -fcxx-exceptions %s -// expected-no-diagnostics // This test is from http://docwiki.embarcadero.com/RADStudio/en/Try @@ -77,3 +76,14 @@ template void Except<void>(); template void Finally<void>(); } + +void test___leave() { + // Most tests are in __try.c. + + // Clang accepts try with __finally. MSVC doesn't. (Maybe a Borland thing?) + // __leave in mixed blocks isn't supported. + try { + __leave; // expected-error{{'__leave' statement not in __try block}} + } __finally { + } +} diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index d7e2d0a3dcf9a..b521196c23b65 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -268,16 +268,16 @@ 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'}}
+ 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/access.cpp b/test/SemaCXX/access.cpp index 5ccd418c1b767..5fa1509c53021 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -136,3 +136,25 @@ namespace PR7434 { }; } } + +namespace LocalExternVar { + class test { + private: + struct private_struct { // expected-note 2{{here}} + int x; + }; + int use_private(); + }; + + int test::use_private() { + extern int array[sizeof(test::private_struct)]; // ok + return array[0]; + } + + int f() { + extern int array[sizeof(test::private_struct)]; // expected-error {{private}} + return array[0]; + } + + int array[sizeof(test::private_struct)]; // expected-error {{private}} +} diff --git a/test/SemaCXX/addr-of-overloaded-function-casting.cpp b/test/SemaCXX/addr-of-overloaded-function-casting.cpp index 784c8a0007445..edf4c138a8402 100644 --- a/test/SemaCXX/addr-of-overloaded-function-casting.cpp +++ b/test/SemaCXX/addr-of-overloaded-function-casting.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s void g(); -void f(); // expected-note 9{{candidate function}} -void f(int); // expected-note 9{{candidate function}} +void f(); // expected-note 11{{candidate function}} +void f(int); // expected-note 11{{candidate function}} template <class T> void t(T); // expected-note 3{{candidate function}} \ @@ -58,4 +58,13 @@ int main() { bool b = static_cast<int (&)(char)>(t); } // expected-error{{does not match required}} { bool b = static_cast<void (&)(char)>(f); } // expected-error{{does not match}} + + { + // The error should be reported when casting overloaded function to the + // compatible function type (not to be confused with function pointer or + // function reference type.) + typedef void (FnType)(int); + FnType a = static_cast<FnType>(f); // expected-error{{address of overloaded function}} + FnType b = (FnType)(f); // expected-error{{address of overloaded function}} + } } diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp index 230a1eb994e19..358fe8d5b08e5 100644 --- a/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -84,7 +84,7 @@ struct C { void h() { // Do not suggest '()' since an int argument is required - q1<int>; // expected-error-re{{reference to non-static member function must be called$}} + q1<int>; // expected-error-re{{reference to non-static member function must be called{{$}}}} // Suggest '()' since there's a default value for the only argument & the // type argument is already provided q2<int>; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} @@ -92,7 +92,7 @@ struct C { // already provided q3<int>; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} // Do not suggest '()' since another type argument is required - q4<int>; // expected-error-re{{reference to non-static member function must be called$}} + q4<int>; // expected-error-re{{reference to non-static member function must be called{{$}}}} // Suggest '()' since the type parameter has a default value q5; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } @@ -220,20 +220,20 @@ namespace test1 { void QualifierTest() { void (Qualifiers::*X)(); - X = &Qualifiers::C; // expected-error {{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const': different qualifiers (none vs const)}} - X = &Qualifiers::V; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile': different qualifiers (none vs volatile)}} - X = &Qualifiers::R; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() restrict': different qualifiers (none vs restrict)}} - X = &Qualifiers::CV; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile': different qualifiers (none vs const and volatile)}} - X = &Qualifiers::CR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const restrict': different qualifiers (none vs const and restrict)}} - X = &Qualifiers::VR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile restrict': different qualifiers (none vs volatile and restrict)}} - X = &Qualifiers::CVR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile restrict': different qualifiers (none vs const, volatile, and restrict)}} + X = &Qualifiers::C; // expected-error-re {{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (none vs const)}} + X = &Qualifiers::V; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (none vs volatile)}} + X = &Qualifiers::R; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} restrict': different qualifiers (none vs restrict)}} + X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (none vs const and volatile)}} + X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const restrict': different qualifiers (none vs const and restrict)}} + X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile restrict': different qualifiers (none vs volatile and restrict)}} + X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile restrict': different qualifiers (none vs const, volatile, and restrict)}} } struct Dummy { void N() {}; }; - void (Qualifiers::*X)() = &Dummy::N; // expected-error{{cannot initialize a variable of type 'void (test1::Qualifiers::*)()' with an rvalue of type 'void (test1::Dummy::*)()': different classes ('test1::Qualifiers' vs 'test1::Dummy')}} + void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (test1::Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': different classes ('test1::Qualifiers' vs 'test1::Dummy')}} } template <typename T> class PR16561 { diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index 885bf703dc108..4e4177463f885 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -49,7 +49,7 @@ struct A { A(int); ~A(); - A(const A&) = delete; // expected-note 2 {{function has been explicitly marked deleted here}} + A(const A&) = delete; // expected-note 2 {{'A' has been explicitly marked deleted here}} }; struct B { diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index db9c82afd5985..89efc501d82ce 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/test/SemaCXX/alias-template.cpp @@ -102,10 +102,10 @@ class CtorDtorName { }; namespace TagName { - template<typename Z> using S = struct { int n; }; // expected-error {{can not be defined}} - template<typename Z> using T = class { int n; }; // expected-error {{can not be defined}} - template<typename Z> using U = enum { a, b, c }; // expected-error {{can not be defined}} - template<typename Z> using V = struct V { int n; }; // expected-error {{'TagName::V' can not be defined in a type alias template}} + template<typename Z> using S = struct { int n; }; // expected-error {{cannot be defined}} + template<typename Z> using T = class { int n; }; // expected-error {{cannot be defined}} + template<typename Z> using U = enum { a, b, c }; // expected-error {{cannot be defined}} + template<typename Z> using V = struct V { int n; }; // expected-error {{'TagName::V' cannot be defined in a type alias template}} } namespace StdExample { @@ -136,7 +136,7 @@ namespace Access { namespace VoidArg { template<typename Z> using V = void; V<int> f(int); // ok - V<char> g(V<double>); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}} + V<char> g(V<double>); // ok (DR577) } namespace Curried { diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp index f0b89eef656dc..011f459abdf2d 100644 --- a/test/SemaCXX/alignof.cpp +++ b/test/SemaCXX/alignof.cpp @@ -62,3 +62,18 @@ const int test8 = __alignof__(S5::x); long long int test14[2]; static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}} + +// PR19992 +static_assert(alignof(int[]) == alignof(int), ""); // ok + +namespace alignof_array_expr { + alignas(32) extern int n[]; + static_assert(alignof(n) == 32, ""); // expected-warning {{GNU extension}} + + template<int> struct S { + static int a[]; + }; + template<int N> int S<N>::a[N]; + // ok, does not complete type of S<-1>::a + static_assert(alignof(S<-1>::a) == alignof(int), ""); // expected-warning {{GNU extension}} +} diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp index 8a61041463bae..1b5dc13cea015 100644 --- a/test/SemaCXX/anonymous-struct.cpp +++ b/test/SemaCXX/anonymous-struct.cpp @@ -14,3 +14,10 @@ struct E { static struct { }; }; + +template <class T> void foo(T); +typedef struct { // expected-note {{use a tag name here to establish linkage prior to definition}} expected-note {{declared here}} + void test() { + foo(this); // expected-warning {{template argument uses unnamed type}} + } +} A; // expected-error {{unsupported: typedef changes linkage of anonymous type, but linkage was already computed}} diff --git a/test/SemaCXX/anonymous-union-cxx11.cpp b/test/SemaCXX/anonymous-union-cxx11.cpp index 9f987a9681cdd..b0dd1a874deb1 100644 --- a/test/SemaCXX/anonymous-union-cxx11.cpp +++ b/test/SemaCXX/anonymous-union-cxx11.cpp @@ -12,3 +12,12 @@ namespace PR12866 { (void)sizeof(bar::member); } } + +namespace PR20021 { +class C { + union { + static_assert(true, ""); + int i; + }; +}; +} diff --git a/test/SemaCXX/ast-print.cpp b/test/SemaCXX/ast-print.cpp index a1975b4ac2644..4851571283f4a 100644 --- a/test/SemaCXX/ast-print.cpp +++ b/test/SemaCXX/ast-print.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -ast-print %s -std=gnu++11 | FileCheck %s // CHECK: r; // CHECK-NEXT: (r->method()); @@ -164,3 +164,47 @@ void test13() { void test14() { struct X { union { int x; } x; }; } + + +// CHECK: float test15() { +// CHECK: return __builtin_asinf(1.F); +// CHECK: } +// CHECK-NOT: extern "C" +float test15() { + return __builtin_asinf(1.0F); +} + +namespace PR18776 { +struct A { + operator void *(); + explicit operator bool(); + A operator&(A); +}; + +// CHECK: struct A +// CHECK-NEXT: {{^[ ]*operator}} void *(); +// CHECK-NEXT: {{^[ ]*explicit}} operator bool(); + +void bar(void *); + +void foo() { + A a, b; + bar(a & b); +// CHECK: bar(a & b); + if (a & b) +// CHECK: if (a & b) + return; +} +}; + +namespace { +void test(int i) { + switch (i) { + case 1: + // CHECK: {{\[\[clang::fallthrough\]\]}} + [[clang::fallthrough]]; + case 2: + break; + } +} +} diff --git a/test/SemaCXX/atomic-type.cxx b/test/SemaCXX/atomic-type.cpp index 947bb3c5f406d..ae18eab5b4a90 100644 --- a/test/SemaCXX/atomic-type.cxx +++ b/test/SemaCXX/atomic-type.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -verify -pedantic %s +// RUN: %clang_cc1 -verify -pedantic %s -std=c++98 +// RUN: %clang_cc1 -verify -pedantic %s -std=c++11 template<typename T> struct atomic { _Atomic(T) value; @@ -48,7 +49,7 @@ typedef _Atomic int(A::*mem_ptr_to_atomic_int); typedef _Atomic(int)&atomic_int_ref; typedef _Atomic int &atomic_int_ref; -typedef _Atomic atomic_int_ref atomic_int_ref; // ok, qualifiers on references ignored in this case. +typedef _Atomic atomic_int_ref atomic_int_ref; // expected-warning {{'_Atomic' qualifier on reference type 'atomic_int_ref' (aka '_Atomic(int) &') has no effect}} typedef int &_Atomic atomic_reference_to_int; // expected-error {{'_Atomic' qualifier may not be applied to a reference}} typedef _Atomic(int &) atomic_reference_to_int; // expected-error {{_Atomic cannot be applied to reference type 'int &'}} @@ -56,3 +57,29 @@ typedef _Atomic(int &) atomic_reference_to_int; // expected-error {{_Atomic cann struct S { _Atomic union { int n; }; // expected-warning {{anonymous union cannot be '_Atomic'}} }; + +namespace copy_init { + struct X { + X(int); + int n; + }; + _Atomic(X) y = X(0); + _Atomic(X) z(X(0)); + void f() { y = X(0); } + + _Atomic(X) e1(0); // expected-error {{cannot initialize}} +#if __cplusplus >= 201103L + _Atomic(X) e2{0}; // expected-error {{illegal initializer}} + _Atomic(X) a{X(0)}; +#endif + + struct Y { + _Atomic(X) a; + _Atomic(int) b; + }; + Y y1 = { X(0), 4 }; + Y y2 = { 0, 4 }; // expected-error {{cannot initialize}} + // FIXME: It's not really clear if we should allow these. Generally, C++11 + // allows extraneous braces around initializers. + Y y3 = { { X(0) }, { 4 } }; // expected-error 2{{illegal initializer type}} +} diff --git a/test/SemaCXX/attr-common.cpp b/test/SemaCXX/attr-common.cpp index 58b30133f52f1..fb98639d1b2ce 100644 --- a/test/SemaCXX/attr-common.cpp +++ b/test/SemaCXX/attr-common.cpp @@ -1,3 +1,3 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -__attribute__((common)) int x; // expected-error {{common attribute is not supported in C++}} +__attribute__((common)) int x; // expected-error {{'common' attribute is not supported in C++}} diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index e24e12e50c4e4..6ba89a62d70de 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -45,3 +45,8 @@ static_assert(alignof(align_class_temp_pack_expr<8, 16, 32>) == 32, "template's static_assert(alignof(outer<int,char>::inner<double,short>) == alignof(int) * alignof(double), "template's alignment is wrong"); static_assert(alignof(int(int)) >= 1, "alignof(function) not positive"); // expected-error{{invalid application of 'alignof' to a function type}} + +[[__carries_dependency__]] // expected-warning{{unknown attribute '__carries_dependency__' ignored}} +void func(void); + +alignas(4) auto PR19252 = 0; diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index b3223f399799f..d28eb75cca657 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 %s -verify -fexceptions class A { - void f() __attribute__((deprecated)); // expected-note 2 {{declared here}} + void f() __attribute__((deprecated)); // expected-note 2 {{'f' has been explicitly marked deprecated here}} void g(A* a); void h(A* a) __attribute__((deprecated)); - int b __attribute__((deprecated)); // expected-note 2 {{declared here}} + int b __attribute__((deprecated)); // expected-note 2 {{'b' has been explicitly marked deprecated here}} }; void A::g(A* a) @@ -26,7 +26,7 @@ void A::h(A* a) } struct B { - virtual void f() __attribute__((deprecated)); // expected-note 4 {{declared here}} + virtual void f() __attribute__((deprecated)); // expected-note 4 {{'f' has been explicitly marked deprecated here}} void g(); }; @@ -68,20 +68,20 @@ void f(D* d) { // Overloaded namespace members. namespace test1 { - void foo(int) __attribute__((deprecated)); // expected-note {{declared here}} + void foo(int) __attribute__((deprecated)); // expected-note {{'foo' has been explicitly marked deprecated here}} void test1() { foo(10); } // expected-warning {{deprecated}} - void foo(short) __attribute__((deprecated)); // expected-note {{declared here}} + void foo(short) __attribute__((deprecated)); // expected-note {{'foo' has been explicitly marked deprecated 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)); // expected-note {{declared here}} + friend void foo(A*) __attribute__((deprecated)); // expected-note {{'foo' has been explicitly marked deprecated here}} }; void test4(A *a) { foo(a); } // expected-warning {{deprecated}} namespace ns { struct Foo {}; - void foo(const Foo &f) __attribute__((deprecated)); // expected-note {{declared here}} + void foo(const Foo &f) __attribute__((deprecated)); // expected-note {{'foo' has been explicitly marked deprecated 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)); // expected-note 2 {{declared here}} + void foo(int) __attribute__((deprecated)); // expected-note 2 {{'foo' has been explicitly marked deprecated here}} void foo(long); - static void bar(int) __attribute__((deprecated)); // expected-note 3 {{declared here}} + static void bar(int) __attribute__((deprecated)); // expected-note 3 {{'bar' has been explicitly marked deprecated 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)); // expected-note {{declared here}} + void operator*(int) __attribute__((deprecated)); // expected-note {{'operator*' has been explicitly marked deprecated here}} void operator-(const A &) const; }; void operator+(const A &, const A &); - void operator+(const A &, int) __attribute__((deprecated)); // expected-note {{declared here}} - void operator-(const A &, int) __attribute__((deprecated)); // expected-note {{declared here}} + void operator+(const A &, int) __attribute__((deprecated)); // expected-note {{'operator+' has been explicitly marked deprecated here}} + void operator-(const A &, int) __attribute__((deprecated)); // expected-note {{'operator-' has been explicitly marked deprecated 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)); // expected-note {{declared here}} + operator intfn() __attribute__((deprecated)); // expected-note {{'operator void (*)(int)' has been explicitly marked deprecated here}} operator unintfn(); - void operator ()(A &) __attribute__((deprecated)); // expected-note {{declared here}} + void operator ()(A &) __attribute__((deprecated)); // expected-note {{'operator()' has been explicitly marked deprecated here}} void operator ()(const A &); }; @@ -163,7 +163,7 @@ namespace test4 { namespace test5 { struct A { - operator int() __attribute__((deprecated)); // expected-note 3 {{declared here}} + operator int() __attribute__((deprecated)); // expected-note 3 {{'operator int' has been explicitly marked deprecated here}} operator long(); }; void test1(A a) { @@ -193,8 +193,8 @@ namespace test5 { // rdar://problem/8518751 namespace test6 { - enum __attribute__((deprecated)) A { // expected-note {{declared here}} - a0 // expected-note {{declared here}} + enum __attribute__((deprecated)) A { // expected-note {{'A' has been explicitly marked deprecated here}} + a0 // expected-note {{'a0' has been explicitly marked deprecated here}} }; void testA() { A x; // expected-warning {{'A' is deprecated}} @@ -202,7 +202,7 @@ namespace test6 { } enum B { - b0 __attribute__((deprecated)), // expected-note {{declared here}} + b0 __attribute__((deprecated)), // expected-note {{'b0' has been explicitly marked deprecated here}} b1 }; void testB() { @@ -212,8 +212,8 @@ namespace test6 { } template <class T> struct C { - enum __attribute__((deprecated)) Enum { // expected-note {{declared here}} - c0 // expected-note {{declared here}} + enum __attribute__((deprecated)) Enum { // expected-note {{'Enum' has been explicitly marked deprecated here}} + c0 // expected-note {{'c0' has been explicitly marked deprecated here}} }; }; void testC() { @@ -224,7 +224,7 @@ namespace test6 { template <class T> struct D { enum Enum { d0, - d1 __attribute__((deprecated)), // expected-note {{declared here}} + d1 __attribute__((deprecated)), // expected-note {{'d1' has been explicitly marked deprecated here}} }; }; void testD() { @@ -236,8 +236,8 @@ namespace test6 { namespace test7 { struct X { - void* operator new(typeof(sizeof(void*))) __attribute__((deprecated)); // expected-note{{'operator new' declared here}} - void operator delete(void *) __attribute__((deprecated)); // expected-note{{'operator delete' declared here}} + void* operator new(typeof(sizeof(void*))) __attribute__((deprecated)); // expected-note{{'operator new' has been explicitly marked deprecated here}} + void operator delete(void *) __attribute__((deprecated)); // expected-note{{'operator delete' has been explicitly marked deprecated here}} }; void test() { @@ -247,6 +247,6 @@ namespace test7 { // rdar://problem/15044218 typedef struct TDS { -} TDS __attribute__((deprecated)); // expected-note {{'TDS' declared here}} +} TDS __attribute__((deprecated)); // expected-note {{'TDS' has been explicitly marked deprecated here}} TDS tds; // expected-warning {{'TDS' is deprecated}} struct TDS tds2; // no warning, attribute only applies to the typedef. diff --git a/test/SemaCXX/attr-flatten.cpp b/test/SemaCXX/attr-flatten.cpp new file mode 100644 index 0000000000000..afcba72b6429e --- /dev/null +++ b/test/SemaCXX/attr-flatten.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int i __attribute__((flatten)); // expected-error {{'flatten' attribute only applies to functions}} + +void f1() __attribute__((flatten)); +void f2() __attribute__((flatten(1))); // expected-error {{'flatten' attribute takes no arguments}} + +template <typename T> +void tf1() __attribute__((flatten)); + +int f3(int __attribute__((flatten)), int); // expected-error{{'flatten' attribute only applies to functions}} + +struct A { + int f __attribute__((flatten)); // expected-error{{'flatten' attribute only applies to functions}} + void mf1() __attribute__((flatten)); + static void mf2() __attribute__((flatten)); +}; + +int ci [[gnu::flatten]]; // expected-error {{'flatten' attribute only applies to functions}} + +[[gnu::flatten]] void cf1(); +[[gnu::flatten(1)]] void cf2(); // expected-error {{'flatten' attribute takes no arguments}} + +template <typename T> +[[gnu::flatten]] +void ctf1(); + +int cf3(int c[[gnu::flatten]], int); // expected-error{{'flatten' attribute only applies to functions}} + +struct CA { + int f [[gnu::flatten]]; // expected-error{{'flatten' attribute only applies to functions}} + [[gnu::flatten]] void mf1(); + [[gnu::flatten]] static void mf2(); +}; diff --git a/test/SemaCXX/attr-no-sanitize-address.cpp b/test/SemaCXX/attr-no-sanitize-address.cpp index f1803496fa55c..9ca28630552bc 100644 --- a/test/SemaCXX/attr-no-sanitize-address.cpp +++ b/test/SemaCXX/attr-no-sanitize-address.cpp @@ -15,23 +15,23 @@ int noanal_testfn(int y) NO_SANITIZE_ADDRESS; int noanal_testfn(int y) { int x NO_SANITIZE_ADDRESS = y; // \ - // expected-error {{'no_sanitize_address' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_address' attribute only applies to functions}} return x; } int noanal_test_var NO_SANITIZE_ADDRESS; // \ - // expected-error {{'no_sanitize_address' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_address' attribute only applies to functions}} class NoanalFoo { private: int test_field NO_SANITIZE_ADDRESS; // \ - // expected-error {{'no_sanitize_address' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_address' attribute only applies to functions}} void test_method() NO_SANITIZE_ADDRESS; }; class NO_SANITIZE_ADDRESS NoanalTestClass { // \ - // expected-error {{'no_sanitize_address' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_address' attribute only applies to functions}} }; void noanal_fun_params(int lvar NO_SANITIZE_ADDRESS); // \ - // expected-error {{'no_sanitize_address' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_address' attribute only applies to functions}} diff --git a/test/SemaCXX/attr-no-sanitize-memory.cpp b/test/SemaCXX/attr-no-sanitize-memory.cpp index d6eca1b69dc17..9cbcb03d6ecf1 100644 --- a/test/SemaCXX/attr-no-sanitize-memory.cpp +++ b/test/SemaCXX/attr-no-sanitize-memory.cpp @@ -15,23 +15,23 @@ int noanal_testfn(int y) NO_SANITIZE_MEMORY; int noanal_testfn(int y) { int x NO_SANITIZE_MEMORY = y; // \ - // expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_memory' attribute only applies to functions}} return x; } int noanal_test_var NO_SANITIZE_MEMORY; // \ - // expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_memory' attribute only applies to functions}} class NoanalFoo { private: int test_field NO_SANITIZE_MEMORY; // \ - // expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_memory' attribute only applies to functions}} void test_method() NO_SANITIZE_MEMORY; }; class NO_SANITIZE_MEMORY NoanalTestClass { // \ - // expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_memory' attribute only applies to functions}} }; void noanal_fun_params(int lvar NO_SANITIZE_MEMORY); // \ - // expected-error {{'no_sanitize_memory' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_memory' attribute only applies to functions}} diff --git a/test/SemaCXX/attr-no-sanitize-thread.cpp b/test/SemaCXX/attr-no-sanitize-thread.cpp index d6372bceff8a3..6cb9c715bf6cc 100644 --- a/test/SemaCXX/attr-no-sanitize-thread.cpp +++ b/test/SemaCXX/attr-no-sanitize-thread.cpp @@ -15,23 +15,23 @@ int noanal_testfn(int y) NO_SANITIZE_THREAD; int noanal_testfn(int y) { int x NO_SANITIZE_THREAD = y; // \ - // expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_thread' attribute only applies to functions}} return x; } int noanal_test_var NO_SANITIZE_THREAD; // \ - // expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_thread' attribute only applies to functions}} class NoanalFoo { private: int test_field NO_SANITIZE_THREAD; // \ - // expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_thread' attribute only applies to functions}} void test_method() NO_SANITIZE_THREAD; }; class NO_SANITIZE_THREAD NoanalTestClass { // \ - // expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_thread' attribute only applies to functions}} }; void noanal_fun_params(int lvar NO_SANITIZE_THREAD); // \ - // expected-error {{'no_sanitize_thread' attribute only applies to functions and methods}} + // expected-error {{'no_sanitize_thread' attribute only applies to functions}} diff --git a/test/SemaCXX/attr-no-split-stack.cpp b/test/SemaCXX/attr-no-split-stack.cpp new file mode 100644 index 0000000000000..3575e9983f41c --- /dev/null +++ b/test/SemaCXX/attr-no-split-stack.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int i __attribute__((no_split_stack)); // expected-error {{'no_split_stack' attribute only applies to functions}} + +void f1() __attribute__((no_split_stack)); +void f2() __attribute__((no_split_stack(1))); // expected-error {{'no_split_stack' attribute takes no arguments}} + +template <typename T> +void tf1() __attribute__((no_split_stack)); + +int f3(int __attribute__((no_split_stack)), int); // expected-error{{'no_split_stack' attribute only applies to functions}} + +struct A { + int f __attribute__((no_split_stack)); // expected-error{{'no_split_stack' attribute only applies to functions}} + void mf1() __attribute__((no_split_stack)); + static void mf2() __attribute__((no_split_stack)); +}; + +int ci [[gnu::no_split_stack]]; // expected-error {{'no_split_stack' attribute only applies to functions}} + +[[gnu::no_split_stack]] void cf1(); +[[gnu::no_split_stack(1)]] void cf2(); // expected-error {{'no_split_stack' attribute takes no arguments}} + +template <typename T> +[[gnu::no_split_stack]] +void ctf1(); + +int cf3(int c[[gnu::no_split_stack]], int); // expected-error{{'no_split_stack' attribute only applies to functions}} + +struct CA { + int f [[gnu::no_split_stack]]; // expected-error{{'no_split_stack' attribute only applies to functions}} + [[gnu::no_split_stack]] void mf1(); + [[gnu::no_split_stack]] static void mf2(); +}; diff --git a/test/SemaCXX/attr-optnone.cpp b/test/SemaCXX/attr-optnone.cpp new file mode 100644 index 0000000000000..eaa50004047c4 --- /dev/null +++ b/test/SemaCXX/attr-optnone.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -verify %s + +int foo() __attribute__((optnone)); +int bar() __attribute__((optnone)) __attribute__((noinline)); + +int baz() __attribute__((always_inline)) __attribute__((optnone)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}} +int quz() __attribute__((optnone)) __attribute__((always_inline)); // expected-error{{'optnone' and 'always_inline' attributes are not compatible}} + +__forceinline __attribute__((optnone)) int bax(); // expected-error{{'__forceinline' and 'optnone' attributes are not compatible}} +__attribute__((optnone)) __forceinline int qux(); // expected-error{{'optnone' and '__forceinline' attributes are not compatible}} + +int globalVar __attribute__((optnone)); // expected-warning{{'optnone' attribute only applies to functions}} + +int fubar(int __attribute__((optnone)), int); // expected-warning{{'optnone' attribute only applies to functions}} + +struct A { + int aField __attribute__((optnone)); // expected-warning{{'optnone' attribute only applies to functions}} +}; + +struct B { + void foo() __attribute__((optnone)); + static void bar() __attribute__((optnone)); +}; + +// Verify that we can specify the [[clang::optnone]] syntax as well. + +[[clang::optnone]] +int foo2(); +[[clang::optnone]] +int bar2() __attribute__((noinline)); + +[[clang::optnone]] +int baz2() __attribute__((always_inline)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}} + +[[clang::optnone]] int globalVar2; //expected-warning{{'optnone' attribute only applies to functions}} + +struct A2 { + [[clang::optnone]] int aField; // expected-warning{{'optnone' attribute only applies to functions}} +}; + +struct B2 { + [[clang::optnone]] + void foo(); + [[clang::optnone]] + static void bar(); +}; + diff --git a/test/SemaCXX/attr-selectany.cpp b/test/SemaCXX/attr-selectany.cpp index 0f9776dbf5db0..c27a9159215ff 100644 --- a/test/SemaCXX/attr-selectany.cpp +++ b/test/SemaCXX/attr-selectany.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify -std=c++11 %s // MSVC produces similar diagnostics. __declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}} @@ -31,3 +31,6 @@ class X { }; __declspec(selectany) X x(1); + +namespace { class Internal {}; } +__declspec(selectany) auto x8 = Internal(); // expected-error {{'selectany' can only be applied to data items with external linkage}} diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp index 2d82668a205a3..51dc8fe3789ef 100644 --- a/test/SemaCXX/attr-unavailable.cpp +++ b/test/SemaCXX/attr-unavailable.cpp @@ -3,7 +3,7 @@ int &foo(int); // expected-note {{candidate}} double &foo(double); // expected-note {{candidate}} void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ -// expected-note{{function has been explicitly marked unavailable here}} +// expected-note{{'foo' has been explicitly marked unavailable here}} void bar(...) __attribute__((__unavailable__)); // expected-note 2{{explicitly marked unavailable}} @@ -37,3 +37,22 @@ void unavail(short* sp) { foo(sp); foo(); } + +// Show that delayed processing of 'unavailable' is the same +// delayed process for 'deprecated'. +// <rdar://problem/12241361> and <rdar://problem/15584219> +enum DeprecatedEnum { DE_A, DE_B } __attribute__((deprecated)); // expected-note {{'DeprecatedEnum' has been explicitly marked deprecated here}} +__attribute__((deprecated)) typedef enum DeprecatedEnum DeprecatedEnum; +typedef enum DeprecatedEnum AnotherDeprecatedEnum; // expected-warning {{'DeprecatedEnum' is deprecated}} + +__attribute__((deprecated)) +DeprecatedEnum testDeprecated(DeprecatedEnum X) { return X; } + + +enum UnavailableEnum { UE_A, UE_B } __attribute__((unavailable)); // expected-note {{'UnavailableEnum' has been explicitly marked unavailable here}} +__attribute__((unavailable)) typedef enum UnavailableEnum UnavailableEnum; +typedef enum UnavailableEnum AnotherUnavailableEnum; // expected-error {{'UnavailableEnum' is unavailable}} + + +__attribute__((unavailable)) +UnavailableEnum testUnavailable(UnavailableEnum X) { return X; } diff --git a/test/SemaCXX/attr-used.cpp b/test/SemaCXX/attr-used.cpp index 9bae3edc7f8b3..65df861f83216 100644 --- a/test/SemaCXX/attr-used.cpp +++ b/test/SemaCXX/attr-used.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -extern char test1[] __attribute__((used)); // expected-warning {{used attribute ignored}} -extern const char test2[] __attribute__((used)); // expected-warning {{used attribute ignored}} +extern char test1[] __attribute__((used)); // expected-warning {{'used' attribute ignored}} +extern const char test2[] __attribute__((used)); // expected-warning {{'used' attribute ignored}} extern const char test3[] __attribute__((used)) = ""; diff --git a/test/SemaCXX/attr-weak.cpp b/test/SemaCXX/attr-weak.cpp index 8939a28d75e1a..8ba3a954282d2 100644 --- a/test/SemaCXX/attr-weak.cpp +++ b/test/SemaCXX/attr-weak.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s static int test0 __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} static void test1() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}} -namespace test2 __attribute__((weak)) { // expected-warning {{'weak' attribute only applies to variables and functions}} +namespace test2 __attribute__((weak)) { // expected-warning {{'weak' attribute only applies to variables, functions and classes}} } namespace { @@ -31,6 +31,10 @@ template <class T> struct Test7 { }; template <class T> int Test7<T>::var; -namespace { class Internal; } +namespace { class Internal {}; } template struct Test7<Internal>; template struct Test7<int>; + +class __attribute__((weak)) Test8 {}; // OK + +__attribute__((weak)) auto Test9 = Internal(); // expected-error {{weak declaration cannot have internal linkage}} diff --git a/test/SemaCXX/attr-weakref.cpp b/test/SemaCXX/attr-weakref.cpp index 0c3f1d20e7f79..46ca5ab206820 100644 --- a/test/SemaCXX/attr-weakref.cpp +++ b/test/SemaCXX/attr-weakref.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s // GCC will accept anything as the argument of weakref. Should we // check for an existing decl? @@ -34,3 +34,5 @@ static int a10(); int a10() __attribute__((weakref ("foo"))); static int v __attribute__((weakref(a1), alias("foo"))); // expected-error {{'weakref' attribute requires a string}} + +__attribute__((weakref ("foo"))) auto a11 = 1; // expected-error {{weakref declaration must have internal linkage}} diff --git a/test/SemaCXX/bool-compare.cpp b/test/SemaCXX/bool-compare.cpp new file mode 100644 index 0000000000000..fe47633bb23b6 --- /dev/null +++ b/test/SemaCXX/bool-compare.cpp @@ -0,0 +1,207 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + + +void f(int x, int y, int z) { + + bool a,b; + + if(b > true) {} // expected-warning {{comparison of true with expression of type 'bool' is always false}} + if(b < true) {} // no warning + if(b >= true) {} // no warning + if(b <= true) {} // expected-warning {{comparison of true with expression of type 'bool' is always true}} + if(b == true) {} // no warning + if(b != true) {} // no warning + + if(b > false) {} // no warning + if(b < false) {} // expected-warning {{comparison of false with expression of type 'bool' is always false}} + if(b >= false) {} // expected-warning {{comparison of false with expression of type 'bool' is always true}} + if(b <= false) {} // no warning + if(b == false) {} // no warning + if(b != false) {} // no warning + + if(b > 1U){} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + + if (a > b) {} // no warning + if (a < b) {} // no warning + if (a >= b) {} // no warning + if (a <= b) {} // no warning + if (a == b) {} // no warning + if (a != b) {} // no warning + + if (a > 0) {} // no warning + if (a > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + if (a > 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + + if (a >= 0) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}} + if (a >= 1) {} // no warning + if (a >= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if (a >= -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if (a <= 0) {} // no warning + if (a <= 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}} + if (a <= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if (a <= -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if (!a > 0) {} // no warning + if (!a > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + if (!a > 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if (!a > y) {} // no warning + if (!a > b) {} // no warning + if (!a > -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if (!a < 0) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}} + if (!a < 1) {} // no warning + if (!a < 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if (!a < y) {} // no warning + if (!a < b) {} // no warning + if (!a < -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if (!a >= 0) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}} + if (!a >= 1) {} // no warning + if (!a >= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if (!a >= y) {} // no warning + if (!a >= b) {} // no warning + if (!a >= -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if (!a <= 0) {} // no warning + if (!a <= 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}} + if (!a <= 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if (!a <= y) {} // no warning + if (!a <= b) {} // no warning + if (!a <= -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if ((a||b) > 0) {} // no warning + if ((a||b) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + if ((a||b) > 4) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}} + if ((a||b) > -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if ((a&&b) > 0) {} // no warning + if ((a&&b) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + if ((a&&b) > 4) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}} + + if ((a<y) > 0) {} // no warning + if ((a<y) > 1) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + if ((a<y) > 4) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always false}} + if ((a<y) > z) {} // no warning + if ((a<y) > -1) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if ((a<y) == 0) {} // no warning + if ((a<y) == 1) {} // no warning + if ((a<y) == 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if ((a<y) == z) {} // no warning + if ((a<y) == -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if ((a<y) != 0) {} // no warning + if ((a<y) != 1) {} // no warning + if ((a<y) != 2) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if ((a<y) != z) {} // no warning + if ((a<y) != -1) {}// expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if ((a<y) == z) {} // no warning + if (a>y<z) {} // no warning + if ((a<y) > z) {} // no warning + if((a<y)>(z<y)) {} // no warning + if((a<y)==(z<y)){} // no warning + if((a<y)!=(z<y)){} // no warning + if((z==x)<(y==z)){} // no warning + if((a<y)!=((z==x)<(y==z))){} // no warning + + + if (0 > !a) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}} + if (1 > !a) {} // no warning + if (2 > !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if (y > !a) {} // no warning + if (-1 > !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if (0 < !a) {} // no warning + if (1 < !a) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always false}} + if (2 < !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if (y < !a) {} // no warning + if (-1 < !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + + if (0 >= !a) {} // no warning + if (1 >= !a) {} // expected-warning {{comparison of constant 1 with expression of type 'bool' is always true}} + if (2 >= !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if (y >= !a) {} // no warning + if (-1 >= !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if (0 <= !a) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always true}} + if (1 <= !a) {} // no warning + if (2 <= !a) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if (y <= !a) {} // + if (-1 <= !a) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if (0 > (a||b)) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}} + if (1 > (a||b)) {} // no warning + if (4 > (a||b)) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}} + + if (0 > (a&&b)) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}} + if (1 > (a&&b)) {} // no warning + if (4 > (a&&b)) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}} + + if (0 > (a<y)) {} // expected-warning {{comparison of constant 0 with expression of type 'bool' is always false}} + if (1 > (a<y)) {} // no warning + if (4 > (a<y)) {} // expected-warning {{comparison of constant 4 with expression of type 'bool' is always true}} + if (z > (a<y)) {} // + if (-1 > (a<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if (0 == (a<y)) {} // no warning + if (1 == (a<y)) {} // no warning + if (2 == (a<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always false}} + if (z == (a<y)) {} // no warning + if (-1 == (a<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + + if (0 !=(a<y)) {} // no warning + if (1 !=(a<y)) {} // no warning + if (2 !=(a<y)) {} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if (z !=(a<y)) {} // no warning + if (-1 !=(a<y)) {} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always true}} + + if (z ==(a<y)) {} // no warning + if (z<a>y) {} // no warning + if (z > (a<y)) {} // no warning + if((z<y)>(a<y)) {} // no warning + if((z<y)==(a<y)){} // no warning + if((z<y)!=(a<y)){} // no warning + if((y==z)<(z==x)){} // no warning + if(((z==x)<(y==z))!=(a<y)){} // no warning + + if(((z==x)<(-1==z))!=(a<y)){} // no warning + if(((z==x)<(z==-1))!=(a<y)){} // no warning + if(((z==x)<-1)!=(a<y)){} // expected-warning {{comparison of constant -1 with expression of type 'bool' is always false}} + if(((z==x)< 2)!=(a<y)){} // expected-warning {{comparison of constant 2 with expression of type 'bool' is always true}} + if(((z==x)<(z>2))!=(a<y)){} // no warning + +} + + +template<typename T, typename U, typename V> struct X6 { + U f(T t, U u, V v) { + // IfStmt + if (t > 0) + return u; + else { + if (t < 0) + return v; // expected-error{{cannot initialize return object of type}} + } + bool r; + // FIXME: We should warn here, DiagRuntimeBehavior does currently not detect this. + if(r<0){} + + if (T x = t) { + t = x; + } + return v; // expected-error{{cannot initialize return object of type}} + } +}; + +struct ConvertibleToInt { + operator int() const; +}; + +template struct X6<ConvertibleToInt, float, char>; +template struct X6<bool, int, int*>; // expected-note{{instantiation}} + + + diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp index bb620c71fa070..237f56458dab3 100644 --- a/test/SemaCXX/c99-variable-length-array.cpp +++ b/test/SemaCXX/c99-variable-length-array.cpp @@ -140,3 +140,24 @@ namespace PR11744 { } int test = f<int>(0); // expected-note {{instantiation of}} } + +namespace pr18633 { + struct A1 { + static const int sz; + static const int sz2; + }; + const int A1::sz2 = 11; + template<typename T> + void func () { + int arr[A1::sz]; // expected-warning{{variable length arrays are a C99 feature}} + } + template<typename T> + void func2 () { + int arr[A1::sz2]; + } + const int A1::sz = 12; + void func2() { + func<int>(); + func2<int>(); + } +} diff --git a/test/SemaCXX/calling-conv-compat.cpp b/test/SemaCXX/calling-conv-compat.cpp index 2d52386add16c..cebac9fad6cdd 100644 --- a/test/SemaCXX/calling-conv-compat.cpp +++ b/test/SemaCXX/calling-conv-compat.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -cxx-abi microsoft -verify -triple i686-pc-win32 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple i686-pc-win32 %s // Pointers to free functions void free_func_default(); @@ -351,24 +351,25 @@ typedef void (__cdecl fun_cdecl)(); typedef void (__stdcall fun_stdcall)(); typedef void (__fastcall fun_fastcall)(); -// FIXME: Adjust cdecl to thiscall when forming a member pointer. -//fun_default A::*td1 = &A::method_thiscall; -fun_cdecl A::*td2 = &A::method_cdecl; +fun_default A::*td1 = &A::method_thiscall; +fun_cdecl A::*td2 = &A::method_thiscall; fun_stdcall A::*td3 = &A::method_stdcall; fun_fastcall A::*td4 = &A::method_fastcall; // Round trip the function type through a template, and verify that only cdecl // gets adjusted. -template<typename Fn> struct X { - typedef Fn A::*p; -}; +template<typename Fn> struct X { typedef Fn A::*p; }; -// FIXME: Adjust cdecl to thiscall when forming a member pointer. -//X<void ()>::p tmpl1 = &A::method_thiscall; -//X<void __cdecl ()>::p tmpl2 = &A::method_thiscall; +X<void ()>::p tmpl1 = &A::method_thiscall; +X<void __cdecl ()>::p tmpl2 = &A::method_thiscall; X<void __stdcall ()>::p tmpl3 = &A::method_stdcall; X<void __fastcall ()>::p tmpl4 = &A::method_fastcall; +X<fun_default >::p tmpl5 = &A::method_thiscall; +X<fun_cdecl >::p tmpl6 = &A::method_thiscall; +X<fun_stdcall >::p tmpl7 = &A::method_stdcall; +X<fun_fastcall>::p tmpl8 = &A::method_fastcall; + } // end namespace MemberPointers // Test that lambdas that capture nothing convert to cdecl function pointers. diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp index 8214f7899ecfc..ef0a524f92f11 100644 --- a/test/SemaCXX/compare.cpp +++ b/test/SemaCXX/compare.cpp @@ -225,7 +225,7 @@ void test3() { } // Test comparison of short to unsigned. If tautological compare does not -// trigger, then the signed comparision warning will. +// trigger, then the signed comparison warning will. void test4(short s) { // A is max short plus 1. All zero and positive shorts are smaller than it. // All negative shorts are cast towards the max unsigned range. Relation diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 5abee4a3c4f85..538de5847de81 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -75,6 +75,7 @@ void test() int i1 = ToBool() ? 0 : 1; // p2 (one or both void, and throwing) + Fields flds; i1 ? throw 0 : throw 1; i1 ? test() : throw 1; i1 ? throw 0 : test(); @@ -85,8 +86,16 @@ void test() i1 = i1 ? 0 : (throw 0); i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}} i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}} - (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}} - (i1 ? i1 : throw 0) = 0; // expected-error {{expression is not assignable}} + (i1 ? throw 0 : i1) = 0; + (i1 ? i1 : throw 0) = 0; + (i1 ? (throw 0) : i1) = 0; + (i1 ? i1 : (throw 0)) = 0; + (i1 ? (void)(throw 0) : i1) = 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}} + (i1 ? i1 : (void)(throw 0)) = 0; // expected-error {{right operand to ? is void, but left operand is of type 'int'}} + int &throwRef1 = (i1 ? flds.i1 : throw 0); + int &throwRef2 = (i1 ? throw 0 : flds.i1); + int &throwRef3 = (i1 ? flds.b1 : throw 0); // expected-error {{non-const reference cannot bind to bit-field}} + int &throwRef4 = (i1 ? throw 0 : flds.b1); // expected-error {{non-const reference cannot bind to bit-field}} // p3 (one or both class type, convert to each other) // b1 (lvalues) @@ -151,7 +160,6 @@ void test() &(i1 ? i1 : i2); // expected-error {{cannot take the address of an rvalue}} // p4 (lvalue, same type) - Fields flds; int &ir1 = i1 ? flds.i1 : flds.i2; (i1 ? flds.b1 : flds.i2) = 0; (i1 ? flds.i1 : flds.b2) = 0; @@ -219,8 +227,8 @@ void test() // *must* create a separate temporary copy of class objects. This can only // be properly tested at runtime, though. - const Abstract &a = true ? static_cast<const Abstract&>(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}} - true ? static_cast<const Abstract&>(Derived1()) : throw 3; // expected-error {{allocating an object of abstract class type 'const Abstract'}} + const Abstract &abstract1 = true ? static_cast<const Abstract&>(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}} + const Abstract &abstract2 = true ? static_cast<const Abstract&>(Derived1()) : throw 3; // ok } namespace PR6595 { @@ -367,3 +375,12 @@ namespace DR587 { 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'}} } + +namespace PR17052 { + struct X { + int i_; + bool b_; + + int &test() { return b_ ? i_ : throw 1; } + }; +} diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp index 1fe350d1977a8..cb9937c50d50c 100644 --- a/test/SemaCXX/const-cast.cpp +++ b/test/SemaCXX/const-cast.cpp @@ -60,7 +60,7 @@ short *bad_const_cast_test(char const *volatile *const volatile *var) // Function pointers. f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} void (A::*mfn)() = 0; - (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}} + (void)const_cast<void (A::*)()>(mfn); // expected-error-re {{const_cast to 'void (A::*)(){{( __attribute__\(\(thiscall\)\))?}}', which is not a reference, pointer-to-object, or pointer-to-data-member}} (void)const_cast<int&&>(0); // expected-error {{const_cast from rvalue to reference type 'int &&'}} expected-warning {{C++11}} return **var3; } diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index d73ee4507f7b9..09d93fa73af1f 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 -Wno-pointer-arith -Wno-zero-length-array -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment +// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion namespace StaticAssertFoldTest { @@ -823,6 +823,19 @@ static_assert(X() == 0, ""); } +struct This { + constexpr int f() const { return 0; } + static constexpr int g() { return 0; } + void h() { + constexpr int x = f(); // expected-error {{must be initialized by a constant}} + // expected-note@-1 {{implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}} + constexpr int y = this->f(); // expected-error {{must be initialized by a constant}} + // expected-note-re@-1 {{{{^}}use of 'this' pointer}} + constexpr int z = g(); + static_assert(z == 0, ""); + } +}; + } namespace Temporaries { @@ -860,6 +873,12 @@ static_assert(f(T(5)) == 5, ""); constexpr bool b(int n) { return &n; } static_assert(b(0), ""); +struct NonLiteral { + NonLiteral(); + int f(); +}; +constexpr int k = NonLiteral().f(); // expected-error {{constant expression}} expected-note {{non-literal type 'Temporaries::NonLiteral'}} + } namespace Union { diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp index 942bf414742b2..e01acdd46f935 100644 --- a/test/SemaCXX/constant-expression.cpp +++ b/test/SemaCXX/constant-expression.cpp @@ -124,3 +124,20 @@ namespace test3 { struct Y { bool b; X x; }; // expected-error {{field has incomplete type 'test3::X'}} int f() { return Y().b; } } + +// PR18283 +namespace test4 { + template <int> struct A {}; + int const i = { 42 }; + // i can be used as non-type template-parameter as "const int x = { 42 };" is + // equivalent to "const int x = 42;" as per C++03 8.5/p13. + typedef A<i> Ai; // ok +} + +// rdar://16064952 +namespace rdar16064952 { + template < typename T > void fn1() { + T b; + unsigned w = ({int a = b.val[sizeof(0)]; 0; }); // expected-warning {{use of GNU statement expression extension}} + } +} diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp index e5b7db50eb65f..9ad11290190f3 100644 --- a/test/SemaCXX/constexpr-value-init.cpp +++ b/test/SemaCXX/constexpr-value-init.cpp @@ -9,7 +9,7 @@ struct B { A a; }; -constexpr A a; // ok, zero initialization preceeds static initialization +constexpr A a; // ok, zero initialization precedes static initialization void f() { constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}} } diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index 17576328c11be..81dc19ea6dfc0 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -94,7 +94,7 @@ struct Current : Derived { Derived::Base1(), // expected-error {{type 'Derived::Base1' is not a direct or virtual base of 'Current'}} Derived::V(), ::NonExisting(), // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} - INT::NonExisting() {} // expected-error {{expected a class or namespace}} \ + INT::NonExisting() {} // expected-error {{'INT' (aka 'int') is not a class, namespace, or scoped enumeration}} \ // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} }; @@ -232,15 +232,14 @@ 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 4 {{candidate}} + 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 {{does not name}} \ - // expected-error {{no member named 'm_String' in 'test3::B'}} \ - // expected-error {{no matching}} + // expected-error {{no member named 'm_String' in 'test3::B'}} } }; } diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp index f3b910d2f5a3b..fa930bdb95dcd 100644 --- a/test/SemaCXX/constructor.cpp +++ b/test/SemaCXX/constructor.cpp @@ -17,6 +17,8 @@ class Foo { int Foo(int, int); // expected-error{{constructor cannot have a return type}} \ // expected-error{{member 'Foo' has the same name as its class}} + + volatile Foo(float); // expected-error{{constructor cannot have a return type}} }; Foo::Foo(const Foo&) { } diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 7eaed54934b3e..40ac33b8eb0df 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -26,6 +26,9 @@ class Y { public: void operator bool(int, ...) const; // expected-error{{conversion function cannot have a return type}} \ // expected-error{{conversion function cannot have any parameters}} + + operator bool(int a = 4, int b = 6) const; // expected-error{{conversion function cannot have any parameters}} + operator float(...) const; // expected-error{{conversion function cannot be variadic}} @@ -405,3 +408,14 @@ namespace PR12712 { A f(const C c) { return c; } } + +namespace PR18234 { + struct A { + operator enum E { e } (); // expected-error {{'PR18234::A::E' cannot be defined in a type specifier}} + operator struct S { int n; } (); // expected-error {{'PR18234::A::S' cannot be defined in a type specifier}} + } a; + A::S s = a; + A::E e = a; // expected-note {{here}} + bool k1 = e == A::e; // expected-error {{no member named 'e'}} + bool k2 = e.n == 0; +} diff --git a/test/SemaCXX/crashes.cpp b/test/SemaCXX/crashes.cpp index 0b15bb0386c21..1570d12eeb2fb 100644 --- a/test/SemaCXX/crashes.cpp +++ b/test/SemaCXX/crashes.cpp @@ -218,3 +218,16 @@ namespace pr12791 { template class basic_stringbuf<char>; } +namespace pr16989 { + class C { + template <class T> + C tpl_mem(T *) { return } // expected-error{{expected expression}} + void mem(int *p) { + tpl_mem(p); + } + }; + class C2 { + void f(); + }; + void C2::f() {} +} diff --git a/test/SemaCXX/cstyle-cast.cpp b/test/SemaCXX/cstyle-cast.cpp index 468c8ecb23c42..afac6a137ec4a 100644 --- a/test/SemaCXX/cstyle-cast.cpp +++ b/test/SemaCXX/cstyle-cast.cpp @@ -227,6 +227,6 @@ void memptrs() void (structure::*psf)() = 0; (void)(int (structure::*)())(psf); - (void)(void (structure::*)())(psi); // expected-error {{C-style cast from 'const int structure::*' to 'void (structure::*)()' is not allowed}} - (void)(int structure::*)(psf); // expected-error {{C-style cast from 'void (structure::*)()' to 'int structure::*' is not allowed}} + (void)(void (structure::*)())(psi); // expected-error-re {{C-style cast from 'const int structure::*' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}} + (void)(int structure::*)(psf); // expected-error-re {{C-style cast from 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' to 'int structure::*' is not allowed}} } diff --git a/test/SemaCXX/cxx-altivec.cpp b/test/SemaCXX/cxx-altivec.cpp new file mode 100644 index 0000000000000..baacbac7d0363 --- /dev/null +++ b/test/SemaCXX/cxx-altivec.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple=powerpc-apple-darwin8 -faltivec -fsyntax-only -verify %s + +struct Vector { + __vector float xyzw; +} __attribute__((vecreturn)) __attribute__((vecreturn)); // expected-error {{'vecreturn' attribute cannot be repeated}} diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp index ffbd20fda373d..a58a7f875cdb3 100644 --- a/test/SemaCXX/cxx0x-compat.cpp +++ b/test/SemaCXX/cxx0x-compat.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++11-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++11-compat -verify %s #if __cplusplus < 201103L @@ -44,5 +44,6 @@ char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal #else auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++1y}} +static_assert(true); // expected-warning {{incompatible with C++ standards before C++1z}} #endif diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index b1078dc404b17..07a7842266408 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -80,3 +80,7 @@ struct except_spec_d_match : except_spec_a, except_spec_b { // (but not normal definitions) struct S { S(); }; S::S() __attribute((pure)) = default; + +using size_t = decltype(sizeof(0)); +void *operator new(size_t) = delete; // expected-error {{deleted definition must be first declaration}} expected-note {{implicit}} +void operator delete(void *) noexcept = delete; // expected-error {{deleted definition must be first declaration}} expected-note {{implicit}} diff --git a/test/SemaCXX/cxx0x-delegating-ctors.cpp b/test/SemaCXX/cxx0x-delegating-ctors.cpp index a34ee4fcb024f..2e1abf53ae99b 100644 --- a/test/SemaCXX/cxx0x-delegating-ctors.cpp +++ b/test/SemaCXX/cxx0x-delegating-ctors.cpp @@ -43,7 +43,7 @@ foo::foo (void*) : foo(4.0f) { } struct deleted_dtor { - ~deleted_dtor() = delete; // expected-note{{function has been explicitly marked deleted here}} + ~deleted_dtor() = delete; // expected-note{{'~deleted_dtor' has been explicitly marked deleted here}} deleted_dtor(); deleted_dtor(int) : deleted_dtor() // expected-error{{attempt to use a deleted function}} {} diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index 0cebc10ade403..b9af67948bfc9 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -59,7 +59,7 @@ struct good_const { good_const gc; struct no_default { - no_default() = delete; // expected-note 3{{deleted here}} + no_default() = delete; // expected-note 4{{deleted here}} }; struct no_dtor { ~no_dtor() = delete; // expected-note 2{{deleted here}} @@ -114,7 +114,7 @@ struct defaulted_delete { defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}} struct late_delete { - no_default nd; + no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}} late_delete(); }; late_delete::late_delete() = default; // expected-error {{would delete it}} diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp index dc179f81bd353..3ea53095d4ea6 100644 --- a/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s struct one { char c[1]; }; struct two { char c[2]; }; @@ -75,8 +75,8 @@ namespace objects { { F<0> f = {}; } // Narrowing conversions don't affect viability. The next two choose // the initializer_list constructor. - { F<3> f{1, 1.0}; } // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} - { F<3> f = {1, 1.0}; } // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{override}} + { F<3> f{1, 1.0}; } // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{silence}} + { F<3> f = {1, 1.0}; } // expected-error {{type 'double' cannot be narrowed to 'int' in initializer list}} expected-note {{silence}} { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } { F<3> f = {1, 2, 3, 4, 5, 6, 7, 8}; } { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } @@ -304,7 +304,6 @@ namespace init_list_default { B b {}; // calls default constructor } - // PR13470, <rdar://problem/11974632> namespace PR13470 { struct W { @@ -365,3 +364,42 @@ namespace PR13470 { yi.h(); // ok, all diagnostics produced in template definition } } + +namespace PR19729 { + struct A { + A(int); + A(const A&) = delete; + }; + struct B { + void *operator new(std::size_t, A); + }; + B *p = new ({123}) B; +} + +namespace PR11410 { + struct A { + A() = delete; // expected-note 2{{deleted here}} + A(int); + }; + + A a[3] = { + {1}, {2} + }; // expected-error {{call to deleted constructor}} \ + expected-note {{in implicit initialization of array element 2 with omitted initializer}} + + struct B { + A a; // expected-note {{in implicit initialization of field 'a'}} + } b = { + }; // expected-error {{call to deleted constructor}} + + struct C { + C(int = 0); // expected-note 2{{candidate}} + C(float = 0); // expected-note 2{{candidate}} + }; + C c[3] = { + 0, 1 + }; // expected-error {{ambiguous}} expected-note {{in implicit initialization of array element 2}} + C c2[3] = { + [0] = 1, [2] = 3 + }; // expected-error {{ambiguous}} expected-note {{in implicit initialization of array element 1}} +} diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp index 627855e96e8cb..1475dcf911c90 100644 --- a/test/SemaCXX/cxx0x-initializer-scalars.cpp +++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -45,8 +45,8 @@ namespace integral { { const int a{1, 2}; } // expected-error {{excess elements}} { const int a = {1, 2}; } // expected-error {{excess elements}} // FIXME: Redundant warnings. - { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} - { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} + { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{insert an explicit cast}} expected-warning {{changes value}} + { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{insert an explicit cast}} expected-warning {{changes value}} { if (const int a{1}) static_assert(a == 1, ""); } { if (const int a = {1}) static_assert(a == 1, ""); } } diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp new file mode 100644 index 0000000000000..774745777c17d --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers %s + +// libstdc++4.6 in debug mode has explicit default constructors. +// stlport has this for all containers. +#ifdef BE_THE_HEADER +#pragma clang system_header +namespace std { +namespace __debug { +template <class T> +class vector { +public: + explicit vector() {} // expected-warning{{should not be explicit}} +}; +} +} +#else + +#define BE_THE_HEADER +#include __FILE__ + +struct { int a, b; std::__debug::vector<int> c; } e[] = { {1, 1} }; // expected-note{{used in initialization here}} + +#endif diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index 9d89cce67b384..70f7c642a5458 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -230,3 +230,32 @@ namespace PR18013 { int f(); std::initializer_list<long (*)()> x = {f}; // expected-error {{cannot initialize an array element of type 'long (*const)()' with an lvalue of type 'int ()': different return type ('long' vs 'int')}} } + +namespace DR1070 { + struct S { + S(std::initializer_list<int>); + }; + S s[3] = { {1, 2, 3}, {4, 5} }; // ok + S *p = new S[3] { {1, 2, 3}, {4, 5} }; // ok +} + +namespace ListInitInstantiate { + struct A { + A(std::initializer_list<A>); + A(std::initializer_list<int>); + }; + struct B : A { + B(int); + }; + template<typename T> struct X { + X(); + A a; + }; + template<typename T> X<T>::X() : a{B{0}, B{1}} {} + + X<int> x; + + int f(const A&); + template<typename T> void g() { int k = f({0}); } + template void g<int>(); +} diff --git a/test/SemaCXX/cxx0x-type-convert-construct.cpp b/test/SemaCXX/cxx0x-type-convert-construct.cpp index 6a7fe45281f5a..25a43d7053ccd 100644 --- a/test/SemaCXX/cxx0x-type-convert-construct.cpp +++ b/test/SemaCXX/cxx0x-type-convert-construct.cpp @@ -9,9 +9,9 @@ void f() { Ustr = U"a UTF-32 string"; // expected-error {{assigning to 'char32_t *' from incompatible type 'const char32_t [16]'}} char *Rstr; - Rstr = R"foo(a raw string)foo"; // expected-warning{{conversion from string literal to 'char *' is deprecated}} + Rstr = R"foo(a raw string)foo"; // expected-warning{{ISO C++11 does not allow conversion from string literal to 'char *'}} wchar_t *LRstr; - LRstr = LR"foo(a wide raw string)foo"; // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}} + LRstr = LR"foo(a wide raw string)foo"; // expected-warning{{ISO C++11 does not allow conversion from string literal to 'wchar_t *'}} char *u8Rstr; u8Rstr = u8R"foo(a UTF-8 raw string)foo"; // expected-error {{assigning to 'char *' from incompatible type 'const char [19]'}} char16_t *uRstr; diff --git a/test/SemaCXX/cxx11-attr-print.cpp b/test/SemaCXX/cxx11-attr-print.cpp index 01325d3c8bf32..999eaed618026 100644 --- a/test/SemaCXX/cxx11-attr-print.cpp +++ b/test/SemaCXX/cxx11-attr-print.cpp @@ -42,9 +42,6 @@ int f3 [[gnu::warn_unused_result]] (); // CHECK: {{\[}}[noreturn]]; void f4 [[noreturn]] (); -// CHECK: {{\[}}[std::noreturn]]; -void f5 [[std::noreturn]] (); - // CHECK: __attribute__((gnu_inline)); inline void f6() __attribute__((gnu_inline)); diff --git a/test/SemaCXX/cxx11-gnu-attrs.cpp b/test/SemaCXX/cxx11-gnu-attrs.cpp index 22d61a1978fb2..9f182249a3e6e 100644 --- a/test/SemaCXX/cxx11-gnu-attrs.cpp +++ b/test/SemaCXX/cxx11-gnu-attrs.cpp @@ -19,8 +19,6 @@ void aliasa [[gnu::alias("_Z6alias1v")]] (); void aligned_fn [[gnu::aligned(32)]] (); struct [[gnu::aligned(8)]] aligned_struct {}; -[[gnu::malloc, gnu::alloc_size(1,2)]] void *alloc_size(int a, int b); - void always_inline [[gnu::always_inline]] (); __thread int tls_model [[gnu::tls_model("local-exec")]]; diff --git a/test/SemaCXX/cxx11-inheriting-ctors.cpp b/test/SemaCXX/cxx11-inheriting-ctors.cpp index 67d55213a0847..04aa117b29dd2 100644 --- a/test/SemaCXX/cxx11-inheriting-ctors.cpp +++ b/test/SemaCXX/cxx11-inheriting-ctors.cpp @@ -26,3 +26,11 @@ namespace PR15757 { return 0; } } + +namespace WrongIdent { + struct A {}; + struct B : A {}; + struct C : B { + using B::A; + }; +} diff --git a/test/SemaCXX/cxx11-unused.cpp b/test/SemaCXX/cxx11-unused.cpp new file mode 100644 index 0000000000000..1e25bd5157247 --- /dev/null +++ b/test/SemaCXX/cxx11-unused.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wunused-parameter + +// PR19303 : Make sure we don't get a unused expression warning for deleted and +// defaulted functions + +// expected-no-diagnostics + +class A { +public: + int x; + A() = default; + ~A() = default; + A(const A &other) = delete; + + template <typename T> + void SetX(T x) { + this->x = x; + }; + + void SetX1(int x); +}; + +template <> +void A::SetX(A x) = delete; + +class B { +public: + B() = default; + ~B() = default; + B(const B &other); +}; + +B::B(const B &other) = default; diff --git a/test/SemaCXX/cxx11-user-defined-literals.cpp b/test/SemaCXX/cxx11-user-defined-literals.cpp index f8bbcd960fd32..cb7796418ee31 100644 --- a/test/SemaCXX/cxx11-user-defined-literals.cpp +++ b/test/SemaCXX/cxx11-user-defined-literals.cpp @@ -141,3 +141,27 @@ namespace PR14950 { int operator"" _b(); // expected-error {{no function template matches function template specialization}} int main() { return 0_b; } // expected-error {{no matching literal operator for call to 'operator "" _b'}} } + +namespace bad_names { + template<char...> int operator""_x(); + + template<typename T> void f() { + class T:: // expected-error {{anonymous class}} expected-warning {{does not declare anything}} + operator // expected-error {{expected identifier}} + ""_q<'a'>; + + T::template operator""_q<'a'>(); // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}} + T::template operator""_q<'a'>::X; // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}} + T::operator""_q<'a'>(); // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}} + typename T::template operator""_q<'a'> a; // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} expected-error +{{}} + typename T::operator""_q(""); // expected-error +{{}} expected-note {{to match}} + T::operator""_q(""); // expected-error {{non-namespace scope 'T::' cannot have a literal operator member}} + + bad_names::operator""_x<'a', 'b', 'c'>(); + }; + + struct S {}; + void g() { + S::operator""_q(); // expected-error {{non-namespace scope 'S::' cannot have a literal operator member}} + } +} diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index d3308b3fd50bf..60864165954ad 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -261,6 +261,13 @@ namespace DefaultedMethods { namespace Constexpr { constexpr auto f1(int n) { return n; } + template<typename T> struct X { constexpr auto f() {} }; // PR18746 + template<typename T> struct Y { constexpr T f() {} }; // expected-note {{control reached end of constexpr function}} + void f() { + X<int>().f(); + Y<void>().f(); + constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to '&Y<int>()->f()'}} + } struct NonLiteral { ~NonLiteral(); } nl; // expected-note {{user-provided destructor}} constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}} } diff --git a/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp b/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp index 8bd4f4242c1df..b08d58abd2a9c 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp @@ -1358,6 +1358,21 @@ template<class R> struct X { int run_char = X<int>{}.foo('a'); int run_int = X<double>{}.foo(4); } - #endif // MS_EXTENSIONS +namespace nsdmi_capturing_this { +struct X { + int m = 10; + int n = [this](auto) { return m; }(20); +}; + +template<class T> +struct XT { + T m = 10; + T n = [this](auto) { return m; }(20); +}; + +XT<int> xt{}; + + +} diff --git a/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp b/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp new file mode 100644 index 0000000000000..b0b86e387721f --- /dev/null +++ b/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING + +namespace explicit_argument_variadics { + + +template<class ... Ts> void print(Ts ... ) { } + +struct X { }; +struct Y { }; +struct Z { }; + +int test() { + { + auto L = [](auto ... as) { }; + L.operator()<bool>(true); + } + { + auto L = [](auto a) { }; + L.operator()<bool>(false); + } + { + auto L = [](auto a, auto b) { }; + L.operator()<bool>(false, 'a'); + } + { + auto L = [](auto a, auto b) { }; + L.operator()<bool, char>(false, 'a'); + } + { + auto L = [](auto a, auto b, auto ... cs) { }; + L.operator()<bool, char>(false, 'a'); + L.operator()<bool, char, const char*>(false, 'a', "jim"); + } + + { + auto L = [](auto ... As) { + }; + L.operator()<bool, double>(false, 3.14, "abc"); + } + { + auto L = [](auto A, auto B, auto ... As) { + }; + L.operator()<bool>(false, 3.14, "abc"); + L.operator()<bool, char>(false, 3.14, "abc"); //expected-warning{{implicit conversion}} + L.operator()<X, Y, bool, Z>(X{}, Y{}, 3.14, Z{}, X{}); //expected-warning{{implicit conversion}} + } + { + auto L = [](auto ... As) { + print("\nL::As = ", As ...); + return [](decltype(As) ... as, auto ... Bs) { + print("\nL::Inner::as = ", as ...); + print("\nL::Inner::Bs = ", Bs ...); + return 4; + }; + }; + auto M = L.operator()<bool, double>(false, 3.14, "abc"); + M(false, 6.26, "jim", true); + M.operator()<bool>(true, 6.26, "jim", false, 3.14); + } + { + auto L = [](auto A, auto ... As) { + print("\nL::As = ", As ...); + return [](decltype(As) ... as, decltype(A) a, auto ... Bs) { + print("\nL::Inner::as = ", as ...); + print("\nL::Inner::Bs = ", Bs ...); + return 4; + }; + }; + auto M = L.operator()<bool, double>(false, 3.14, "abc"); + M(6.26, "jim", true); + M.operator()<X>(6.26, "jim", false, X{}, Y{}, Z{}); + } + + return 0; +} + int run = test(); +} // end ns explicit_argument_extension + + + +#ifdef PR18499_FIXED +namespace variadic_expansion { + void f(int &, char &); + + template <typename ... T> void g(T &... t) { + f([&a(t)]()->decltype(auto) { + return a; + }() ...); + f([&a(f([&b(t)]()->decltype(auto) { return b; }()...), t)]()->decltype(auto) { + return a; + }()...); + } + + void h(int i, char c) { g(i, c); } +} +#endif + diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 20e06f48a1ce3..dc8574825dd98 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -3,6 +3,17 @@ // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING +template<class F, class ...Rest> struct first_impl { typedef F type; }; +template<class ...Args> using first = typename first_impl<Args...>::type; + +namespace simple_explicit_capture { + void test() { + int i; + auto L = [i](auto a) { return i + a; }; + L(3.14); + } +} + namespace explicit_call { int test() { auto L = [](auto a) { return a; }; @@ -489,8 +500,6 @@ int run = fooT('a') + fooT(3.14); template<class ... Ts> void print(Ts ... ts) { } -template<class F, class ... Rest> using first = F; - template<class ... Ts> auto fooV(Ts ... ts) { auto L = [](auto ... a) { auto M = [](decltype(a) ... b) { @@ -560,7 +569,6 @@ int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expe namespace variadic_tests_1 { template<class ... Ts> void print(Ts ... ts) { } -template<class F, class ... Rest> using FirstType = F; template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; } template<class ... Ts> int fooV(Ts ... ts) { @@ -574,7 +582,7 @@ template<class ... Ts> int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType<Ts...>{}); + N(first<Ts...>{}); }; M(a...); print("a = ", a..., "\n"); @@ -599,7 +607,7 @@ template<class ... Ts> int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType<Ts...>{}); + N(first<Ts...>{}); }; M(a...); return M; @@ -619,7 +627,7 @@ template<class ... Ts> int fooV(Ts ... ts) { }; N('a'); N(N); - N(FirstType<Ts...>{}); + N(first<Ts...>{}); return N; }; M(a...); @@ -763,7 +771,6 @@ int run = test(); namespace fptr_with_decltype_return_type { -template<class F, class ... Ts> using FirstType = F; template<class F, class ... Rest> F& FirstArg(F& f, Rest& ... r) { return f; }; template<class ... Ts> auto vfun(Ts&& ... ts) { print(ts...); @@ -774,7 +781,7 @@ int test() { auto L = [](auto ... As) { return [](auto b) ->decltype(b) { - vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(FirstType<decltype(As)...>{}); + vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(first<decltype(As)...>{}); return decltype(b){}; }; }; @@ -905,4 +912,4 @@ int run2 = x2.fooG3(); -} //end ns inclass_lambdas_within_nested_classes
\ No newline at end of file +} //end ns inclass_lambdas_within_nested_classes diff --git a/test/SemaCXX/cxx1y-init-captures.cpp b/test/SemaCXX/cxx1y-init-captures.cpp index 2cb4d31ffc4bd..64fe50a70e784 100644 --- a/test/SemaCXX/cxx1y-init-captures.cpp +++ b/test/SemaCXX/cxx1y-init-captures.cpp @@ -36,7 +36,7 @@ namespace variadic_expansion { namespace odr_use_within_init_capture { int test() { - + { // no captures const int x = 10; auto L = [z = x + 2](int a) { diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index 94d0f16f06ede..1e5e834b6d2a0 100644 --- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -39,11 +39,11 @@ namespace out_of_line { template<typename T> CONST T B1::right<T,int> = T(5); class B2 { - template<typename T, typename T0> static CONST T right = T(100); // expected-note {{previous definition is here}} - template<typename T> static CONST T right<T,int> = T(5); // expected-note {{previous definition is here}} + template<typename T, typename T0> static CONST T right = T(100); // expected-note {{previous initialization is here}} + template<typename T> static CONST T right<T,int> = T(5); // expected-note {{previous initialization is here}} }; - template<typename T, typename T0> CONST T B2::right = T(100); // expected-error {{redefinition of 'right'}} - template<typename T> CONST T B2::right<T,int> = T(5); // expected-error {{redefinition of 'right'}} + template<typename T, typename T0> CONST T B2::right = T(100); // expected-error {{static data member 'right' already has an initializer}} + template<typename T> CONST T B2::right<T,int> = T(5); // expected-error {{static data member 'right' already has an initializer}} class B3 { template<typename T, typename T0> static CONST T right = T(100); @@ -291,6 +291,30 @@ namespace in_class_template { template<typename T> template<typename...U> T A<T>::y<tuple<U...> >[] = { U()... }; static_assert(sizeof(A<int>::y<tuple<char, char, char> >) == 12, ""); } + + namespace bad_reference { + struct S { + template<typename T> static int A; // expected-note 4{{here}} + }; + + template<typename T> void f() { + typename T::template A<int> a; // expected-error {{template name refers to non-type template 'S::A'}} + } + template<typename T> void g() { + T::template A<int>::B = 0; // expected-error {{template name refers to non-type template 'S::A'}} + } + template<typename T> void h() { + class T::template A<int> c; // expected-error {{template name refers to non-type template 'S::A'}} + } + + template<typename T> + struct X : T::template A<int> {}; // expected-error {{template name refers to non-type template 'S::A'}} + + template void f<S>(); // expected-note {{in instantiation of}} + template void g<S>(); // expected-note {{in instantiation of}} + template void h<S>(); // expected-note {{in instantiation of}} + template struct X<S>; // expected-note {{in instantiation of}} + } } namespace in_nested_classes { diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index b6e8762f5d59d..4e62941e68188 100644 --- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -81,7 +81,7 @@ namespace odr_tmpl { template<typename T> T v; // expected-note {{previous definition is here}} template<typename T> int v; // expected-error {{redefinition of 'v'}} - template<typename T> int v1; // expected-note {{previous template declaration is here}} + template<typename T> extern int v1; // expected-note {{previous template declaration is here}} template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}} } namespace pvt_use { @@ -90,11 +90,8 @@ namespace odr_tmpl { } namespace pvt_diff_params { - // FIXME: (?) Redefinitions should simply be not allowed, whether the - // template parameters match or not. However, this current behaviour also - // matches that of class templates... - template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}} - template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} + template<typename T, typename> T v; // expected-note {{previous template declaration is here}} + template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} expected-note {{previous template declaration is here}} template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}} } @@ -327,7 +324,7 @@ namespace narrowing { template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}} #ifndef PRECXX11 // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\ - // expected-note@-2 {{override this message by inserting an explicit cast}} + // expected-note@-2 {{insert an explicit cast to silence this issue}} #endif int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}} } @@ -391,7 +388,7 @@ namespace nested { namespace n1 { template<typename T> - T pi1a = T(3.1415926535897932385); + T pi1a = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} #ifndef PRECXX11 // expected-note@-2 {{explicit instantiation refers here}} #endif @@ -413,7 +410,7 @@ namespace nested { #endif float f1 = pi1a<float>; - template<> double pi1a<double> = 5.2; // expected-error {{no variable template matches specialization}} + template<> double pi1a<double> = 5.2; // expected-error {{variable template specialization of 'pi1a' must originally be declared in namespace 'n1'}} double d1 = pi1a<double>; } @@ -432,3 +429,32 @@ namespace nested { } } +namespace nested_name { + template<typename T> int a; // expected-note {{variable template 'a' declared here}} + a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}} + + class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}} + enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}} +} + +namespace PR18530 { + template<typename T> int a; + int a<int>; // expected-error {{requires 'template<>'}} +} + +namespace PR19152 { +#ifndef PRECXX11 + template<typename T> const auto x = 1; + static_assert(x<int> == 1, ""); +#endif +} + +namespace PR19169 { + template <typename T> int* f(); + template <typename T> void f(); + template<> int f<double>; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}} + + template <typename T> void g(); + template<> int g<double>; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}} +} + diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 9690638ce0256..96af95425aecc 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -23,7 +23,7 @@ template<int ...I> // expected-warning {{variadic templates are incompatible wi class Variadic3 {}; alignas(8) int with_alignas; // expected-warning {{'alignas' is incompatible with C++98}} -int with_attribute [[ ]]; // expected-warning {{attributes are incompatible with C++98}} +int with_attribute [[ ]]; // expected-warning {{C++11 attribute syntax is incompatible with C++98}} void Literals() { (void)u8"str"; // expected-warning {{unicode literals are incompatible with C++98}} @@ -219,18 +219,11 @@ int n = {}; // expected-warning {{scalar initialized from empty initializer list class PrivateMember { struct ImPrivate {}; }; -template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}} +template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} return typename T::ImPrivate(); } int SFINAEAccessControl(...) { return 0; } -int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember()); - -template<typename T> -struct FriendRedefinition { - friend void Friend() {} // expected-warning {{friend function 'Friend' would be implicitly redefined in C++98}} expected-note {{previous}} -}; -FriendRedefinition<int> FriendRedef1; -FriendRedefinition<char> FriendRedef2; // expected-note {{requested here}} +int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember()); // expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}} namespace CopyCtorIssues { struct Private { @@ -386,38 +379,22 @@ template<typename T> T var = T(10); // expected-warning@-4 {{variable templates are a C++1y extension}} #endif +// No diagnostic for specializations of variable templates; we will have +// diagnosed the primary template. template<typename T> T* var<T*> = new T(); -#ifdef CXX1YCOMPAT -// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} -#else -// expected-warning@-4 {{variable templates are a C++1y extension}} -#endif - template<> int var<int> = 10; -#ifdef CXX1YCOMPAT -// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} -#else -// expected-warning@-4 {{variable templates are a C++1y extension}} -#endif - template int var<int>; float fvar = var<float>; -class A { +class A { template<typename T> static T var = T(10); #ifdef CXX1YCOMPAT // expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} #else // expected-warning@-4 {{variable templates are a C++1y extension}} #endif - - template<typename T> static T* var<T*> = new T(); -#ifdef CXX1YCOMPAT -// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} -#else -// expected-warning@-4 {{variable templates are a C++1y extension}} -#endif + template<typename T> static T* var<T*> = new T(); }; struct B { template<typename T> static T v; }; @@ -435,19 +412,7 @@ template<typename T> T B::v = T(); #endif template<typename T> T* B::v<T*> = new T(); -#ifdef CXX1YCOMPAT -// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} -#else -// expected-warning@-4 {{variable templates are a C++1y extension}} -#endif - template<> int B::v<int> = 10; -#ifdef CXX1YCOMPAT -// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} -#else -// expected-warning@-4 {{variable templates are a C++1y extension}} -#endif - template int B::v<int>; float fsvar = B::v<float>; diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp index 8c5e654fca2ef..432c116466111 100644 --- a/test/SemaCXX/dcl_init_aggr.cpp +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -46,7 +46,7 @@ struct NoDefaultConstructor { // expected-note 3 {{candidate constructor (the im }; struct TooFewError { // expected-error{{implicit default constructor for}} int a; - NoDefaultConstructor nodef; // expected-note{{member is declared here}} + NoDefaultConstructor nodef; // expected-note{{member is declared here}} expected-note 2{{in implicit initialization of field 'nodef'}} }; TooFewError too_few_okay = { 1, 1 }; TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} @@ -54,7 +54,7 @@ TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} TooFewError too_few_okay2[2] = { 1, 1 }; // expected-note{{implicit default constructor for 'TooFewError' first required here}} TooFewError too_few_error2[2] = { 1 }; // expected-error{{no matching constructor}} -NoDefaultConstructor too_few_error3[3] = { }; // expected-error {{no matching constructor}} +NoDefaultConstructor too_few_error3[3] = { }; // expected-error {{no matching constructor}} expected-note {{implicit initialization of array element 0}} // C++ [dcl.init.aggr]p8 struct Empty { }; diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 8164b2bc91e72..6abfb2f328747 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -33,7 +33,7 @@ void f() { extern T f3(); __typeof(*T()) f4(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} typedef void *V; - __typeof(*V()) f5(); + __typeof(*V()) f5(); // expected-error {{ISO C++ does not allow indirection on operand of type 'V' (aka 'void *')}} T multi1, multi2(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} T(d)[5]; // expected-error {{redefinition of 'd'}} diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp index 9f1463245ba29..eb6c8507eddcb 100644 --- a/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -fms-extensions -verify %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -verify %s +// RUN: %clang_cc1 -triple i686-pc-mingw32 -verify %s +// RUN: %clang_cc1 -triple i686-pc-mingw32 -fms-extensions -verify %s typedef void void_fun_t(); typedef void __cdecl cdecl_fun_t(); @@ -191,3 +193,41 @@ namespace test5 { }; extern template void valarray<int>::bar(); } + +namespace test6 { + struct foo { + int bar(); + }; + typedef int bar_t(); + void zed(bar_t foo::*) { + } + void baz() { + zed(&foo::bar); + } +} + +namespace test7 { + template <typename T> + struct S { + void f(T t) { + t = 42; + } + }; + template<> void S<void*>::f(void*); + void g(S<void*> s, void* p) { + s.f(p); + } +} + +namespace test8 { + template <typename T> + struct S { + void f(T t) { // expected-note {{previous declaration is here}} + t = 42; // expected-error {{assigning to 'void *' from incompatible type 'int'}} + } + }; + template<> void __cdecl S<void*>::f(void*); // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} + void g(S<void*> s, void* p) { + s.f(p); // expected-note {{in instantiation of member function 'test8::S<void *>::f' requested here}} + } +} diff --git a/test/SemaCXX/declspec-thread.cpp b/test/SemaCXX/declspec-thread.cpp new file mode 100644 index 0000000000000..0ace9a65a4c57 --- /dev/null +++ b/test/SemaCXX/declspec-thread.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -std=c++11 -fms-extensions -verify %s + +__thread __declspec(thread) int a; // expected-error {{already has a thread-local storage specifier}} +__declspec(thread) __thread int b; // expected-error {{already has a thread-local storage specifier}} +__declspec(thread) int c(); // expected-warning {{only applies to variables}} +__declspec(thread) int d; +int foo(); +__declspec(thread) int e = foo(); // expected-error {{must be a constant expression}} expected-note {{thread_local}} + +struct HasCtor { HasCtor(); int x; }; +__declspec(thread) HasCtor f; // expected-error {{must be a constant expression}} expected-note {{thread_local}} + +struct HasDtor { ~HasDtor(); int x; }; +__declspec(thread) HasDtor g; // expected-error {{non-trivial destruction}} expected-note {{thread_local}} + +struct HasDefaultedDefaultCtor { + HasDefaultedDefaultCtor() = default; + int x; +}; +__declspec(thread) HasDefaultedDefaultCtor h; + +struct HasConstexprCtor { + constexpr HasConstexprCtor(int x) : x(x) {} + int x; +}; +__declspec(thread) HasConstexprCtor i(42); + +int foo() { + __declspec(thread) int a; // expected-error {{must have global storage}} + static __declspec(thread) int b; +} + +extern __declspec(thread) int fwd_thread_var; +__declspec(thread) int fwd_thread_var = 5; + +extern int fwd_thread_var_mismatch; // expected-note {{previous declaration}} +__declspec(thread) int fwd_thread_var_mismatch = 5; // expected-error-re {{thread-local {{.*}} follows non-thread-local}} + +extern __declspec(thread) int thread_mismatch_2; // expected-note {{previous declaration}} +int thread_mismatch_2 = 5; // expected-error-re {{non-thread-local {{.*}} follows thread-local}} + +typedef __declspec(thread) int tls_int_t; // expected-warning {{only applies to variables}} diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp index d6e85d285dd14..f1900b2b830f0 100644 --- a/test/SemaCXX/decltype.cpp +++ b/test/SemaCXX/decltype.cpp @@ -16,6 +16,27 @@ void test_f2() { float &fr = f2(AC().a); } +template <class T> +struct Future { + explicit Future(T v); + + template <class F> + auto call(F&& fn) -> decltype(fn(T())) { + return fn(T()); + } + + template <class B, class F> + auto then(F&& fn) -> decltype(call(fn)) + { + return fn(T()); + } +}; + +void rdar16527205() { + Future<int> f1(42); + f1.call([](int){ return Future<float>(0); }); +} + namespace pr10154 { class A{ A(decltype(nullptr) param); @@ -45,6 +66,16 @@ namespace PR16529 { U &r = S<int>::f(); } +namespace PR18876 { + struct A { ~A() = delete; }; // expected-note +{{here}} + A f(); + decltype(f()) *a; // ok, function call + decltype(A()) *b; // expected-error {{attempt to use a deleted function}} + decltype(0, f()) *c; // ok, function call on RHS of comma + decltype(0, A()) *d; // expected-error {{attempt to use a deleted function}} + decltype(f(), 0) *e; // expected-error {{attempt to use a deleted function}} +} + template<typename> class conditional { }; diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp index b661776b6ef58..23466fac62aaa 100644 --- a/test/SemaCXX/default1.cpp +++ b/test/SemaCXX/default1.cpp @@ -62,3 +62,6 @@ int i2() { j(2, 3); // expected-error{{too many arguments to function call, expected at most single argument 'f', have 2}} } } + +int pr20055_f(int x = 0, int y = UNDEFINED); // expected-error{{use of undeclared identifier}} +int pr20055_v = pr20055_f(0); diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index e78e7edc71998..d7ef9b263d881 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -15,9 +15,9 @@ void ov(int) {} // expected-note {{candidate function}} void ov(double) = delete; // expected-note {{candidate function has been explicitly deleted}} struct WithDel { - WithDel() = delete; // expected-note {{function has been explicitly marked deleted here}} - void fn() = delete; // expected-note {{function has been explicitly marked deleted here}} - operator int() = delete; // expected-note {{function has been explicitly marked deleted here}} + WithDel() = delete; // expected-note {{'WithDel' has been explicitly marked deleted here}} + void fn() = delete; // expected-note {{'fn' has been explicitly marked deleted here}} + operator int() = delete; // expected-note {{'operator int' has been explicitly marked deleted here}} void operator +(int) = delete; int i = delete; // expected-error {{only functions can have deleted definitions}} diff --git a/test/SemaCXX/deleted-operator.cpp b/test/SemaCXX/deleted-operator.cpp index 9f53e71d456c3..df67978a36d6c 100644 --- a/test/SemaCXX/deleted-operator.cpp +++ b/test/SemaCXX/deleted-operator.cpp @@ -13,6 +13,7 @@ int PR10757f() { } struct DelOpDel { - virtual ~DelOpDel() {} // expected-error {{deleted function}} - void operator delete(void*) = delete; // expected-note {{deleted here}} + // FIXME: In MS ABI, we error twice below. + virtual ~DelOpDel() {} // expected-error 1-2 {{attempt to use a deleted function}} + void operator delete(void*) = delete; // expected-note 1-2 {{deleted here}} }; diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp index 0335a80ffc5d5..2fe6d59861ac5 100644 --- a/test/SemaCXX/deprecated.cpp +++ b/test/SemaCXX/deprecated.cpp @@ -24,12 +24,15 @@ void stuff() { register int m asm("rbx"); // no-warning int k = to_int(n); // no-warning - bool b; ++b; // expected-warning {{incrementing expression of type bool is deprecated}} - // FIXME: This is ill-formed in C++11. - char *p = "foo"; // expected-warning {{conversion from string literal to 'char *' is deprecated}} + char *p = "foo"; +#if __cplusplus < 201103L + // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}} +#else + // expected-warning@-4 {{ISO C++11 does not allow conversion from string literal to 'char *'}} +#endif } struct S { int n; }; diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index e511be0116621..5305ff5f7ca65 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s class A { public: ~A(); @@ -83,6 +84,12 @@ namespace PR6421 { } namespace PR6709 { +#ifdef MSABI + // This bug, "Clang instantiates destructor for function argument" is intended + // behaviour in the Microsoft ABI because the callee needs to destruct the arguments. + // expected-error@+3 {{indirection requires pointer operand ('int' invalid)}} + // expected-note@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}} +#endif template<class T> class X { T v; ~X() { ++*v; } }; void a(X<int> x) {} } @@ -100,10 +107,16 @@ namespace test6 { T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}} } +#ifdef MSABI + // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}} +#endif virtual ~A() {} }; - class B : A<int> { B(); }; // expected-note {{in instantiation of member function 'test6::A<int>::operator delete' requested here}} +#ifndef MSABI + // expected-note@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}} +#endif + class B : A<int> { B(); }; B::B() {} } @@ -182,7 +195,7 @@ struct B { // expected-warning {{has virtual functions but non-virtual destructo struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} -struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} +struct F final : B {}; struct VB { virtual void foo(); @@ -367,3 +380,9 @@ namespace PR7900 { namespace PR16892 { auto p = &A::~A; // expected-error{{taking the address of a destructor}} } + +namespace PR20238 { +struct S { + volatile ~S() { } // expected-error{{destructor cannot have a return type}} +}; +} diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp new file mode 100644 index 0000000000000..50d163a7f20f8 --- /dev/null +++ b/test/SemaCXX/dllexport.cpp @@ -0,0 +1,1010 @@ +// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 -DMS %s +// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y -DMS %s +// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Exported {}; +struct ExplicitDecl_Exported {}; +struct ExplicitInst_Exported {}; +struct ExplicitSpec_Exported {}; +struct ExplicitSpec_Def_Exported {}; +struct ExplicitSpec_InlineDef_Exported {}; +struct ExplicitSpec_NotExported {}; +namespace { struct Internal {}; } +struct External { int v; }; + + +// Invalid usage. +__declspec(dllexport) typedef int typedef1; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllexport) int typedef2; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +typedef int __declspec(dllexport) typedef3; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllexport) void (*FunTy)(); // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +enum __declspec(dllexport) Enum {}; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +#if __has_feature(cxx_strong_enums) + enum class __declspec(dllexport) EnumClass {}; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} +#endif + + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Export declaration. +__declspec(dllexport) extern int ExternGlobalDecl; + +// dllexport implies a definition. +__declspec(dllexport) int GlobalDef; + +// Export definition. +__declspec(dllexport) int GlobalInit1 = 1; +int __declspec(dllexport) GlobalInit2 = 1; + +// Declare, then export definition. +__declspec(dllexport) extern int GlobalDeclInit; +int GlobalDeclInit = 1; + +// Redeclarations +__declspec(dllexport) extern int GlobalRedecl1; +__declspec(dllexport) int GlobalRedecl1; + +__declspec(dllexport) extern int GlobalRedecl2; + int GlobalRedecl2; + + extern int GlobalRedecl3; // expected-note{{previous declaration is here}} +__declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}} + +// External linkage is required. +__declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} +__declspec(dllexport) Internal InternalTypeGlobal; // expected-error{{'InternalTypeGlobal' must have external linkage when declared 'dllexport'}} +namespace { __declspec(dllexport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllexport'}} +namespace ns { __declspec(dllexport) int ExternalGlobal; } + +__declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}} +__declspec(dllexport) auto ExternalAutoTypeGlobal = External(); + +// Export in local scope. +void functionScope() { + __declspec(dllexport) int LocalVarDecl; // expected-error{{'LocalVarDecl' must have external linkage when declared 'dllexport'}} + __declspec(dllexport) int LocalVarDef = 1; // expected-error{{'LocalVarDef' must have external linkage when declared 'dllexport'}} + __declspec(dllexport) extern int ExternLocalVarDecl; + __declspec(dllexport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllexport'}} +} + + + +//===----------------------------------------------------------------------===// +// Variable templates +//===----------------------------------------------------------------------===// +#if __has_feature(cxx_variable_templates) + +// Export declaration. +template<typename T> __declspec(dllexport) extern int ExternVarTmplDecl; + +// dllexport implies a definition. +template<typename T> __declspec(dllexport) int VarTmplDef; + +// Export definition. +template<typename T> __declspec(dllexport) int VarTmplInit1 = 1; +template<typename T> int __declspec(dllexport) VarTmplInit2 = 1; + +// Declare, then export definition. +template<typename T> __declspec(dllexport) extern int VarTmplDeclInit; +template<typename T> int VarTmplDeclInit = 1; + +// Redeclarations +template<typename T> __declspec(dllexport) extern int VarTmplRedecl1; +template<typename T> __declspec(dllexport) int VarTmplRedecl1 = 1; + +template<typename T> __declspec(dllexport) extern int VarTmplRedecl2; +template<typename T> int VarTmplRedecl2 = 1; + +template<typename T> extern int VarTmplRedecl3; // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllexport) extern int VarTmplRedecl3; // expected-error{{redeclaration of 'VarTmplRedecl3' cannot add 'dllexport' attribute}} + +// External linkage is required. +template<typename T> __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllexport'}} +template<typename T> __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllexport'}} +namespace { template<typename T> __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}} +namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; } + +template<typename T> __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllexport'}} +template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External(); +template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>; + + +template<typename T> int VarTmpl = 1; +template<typename T> __declspec(dllexport) int ExportedVarTmpl = 1; + +// Export implicit instantiation of an exported variable template. +int useVarTmpl() { return ExportedVarTmpl<ImplicitInst_Exported>; } + +// Export explicit instantiation declaration of an exported variable template. +extern template int ExportedVarTmpl<ExplicitDecl_Exported>; + template int ExportedVarTmpl<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of an exported variable template. +template __declspec(dllexport) int ExportedVarTmpl<ExplicitInst_Exported>; + +// Export specialization of an exported variable template. +template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Exported>; +template<> __declspec(dllexport) int ExportedVarTmpl<ExplicitSpec_Def_Exported> = 1; + +// Not exporting specialization of an exported variable template without +// explicit dllexport. +template<> int ExportedVarTmpl<ExplicitSpec_NotExported>; + + +// Export explicit instantiation declaration of a non-exported variable template. +extern template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; + template __declspec(dllexport) int VarTmpl<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of a non-exported variable template. +template __declspec(dllexport) int VarTmpl<ExplicitInst_Exported>; + +// Export specialization of a non-exported variable template. +template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Exported>; +template<> __declspec(dllexport) int VarTmpl<ExplicitSpec_Def_Exported> = 1; + +#endif // __has_feature(cxx_variable_templates) + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Export function declaration. Check different placements. +__attribute__((dllexport)) void decl1A(); // Sanity check with __attribute__ +__declspec(dllexport) void decl1B(); + +void __attribute__((dllexport)) decl2A(); +void __declspec(dllexport) decl2B(); + +// Export function definition. +__declspec(dllexport) void def() {} + +// extern "C" +extern "C" __declspec(dllexport) void externC() {} + +// Export inline function. +__declspec(dllexport) inline void inlineFunc1() {} +inline void __attribute__((dllexport)) inlineFunc2() {} + +__declspec(dllexport) inline void inlineDecl(); + void inlineDecl() {} + +__declspec(dllexport) void inlineDef(); + inline void inlineDef() {} + +// Redeclarations +__declspec(dllexport) void redecl1(); +__declspec(dllexport) void redecl1() {} + +__declspec(dllexport) void redecl2(); + void redecl2() {} + + void redecl3(); // expected-note{{previous declaration is here}} +__declspec(dllexport) void redecl3(); // expected-error{{redeclaration of 'redecl3' cannot add 'dllexport' attribute}} + + void redecl4(); // expected-note{{previous declaration is here}} +__declspec(dllexport) inline void redecl4() {} // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} + +// Friend functions +struct FuncFriend { + friend __declspec(dllexport) void friend1(); + friend __declspec(dllexport) void friend2(); + friend void friend3(); // expected-note{{previous declaration is here}} + friend void friend4(); // expected-note{{previous declaration is here}} +}; +__declspec(dllexport) void friend1() {} + void friend2() {} +__declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'friend3' cannot add 'dllexport' attribute}} +__declspec(dllexport) inline void friend4() {} // expected-error{{redeclaration of 'friend4' cannot add 'dllexport' attribute}} + +// Implicit declarations can be redeclared with dllexport. +__declspec(dllexport) void* operator new(__SIZE_TYPE__ n); + +// External linkage is required. +__declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}} +__declspec(dllexport) Internal internalRetFunc(); // expected-error{{'internalRetFunc' must have external linkage when declared 'dllexport'}} +namespace { __declspec(dllexport) void internalFunc() {} } // expected-error{{'(anonymous namespace)::internalFunc' must have external linkage when declared 'dllexport'}} +namespace ns { __declspec(dllexport) void externalFunc() {} } + +// Export deleted function. +__declspec(dllexport) void deletedFunc() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} +__declspec(dllexport) inline void deletedInlineFunc() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + + + +//===----------------------------------------------------------------------===// +// Function templates +//===----------------------------------------------------------------------===// + +// Export function template declaration. Check different placements. +template<typename T> __declspec(dllexport) void funcTmplDecl1(); +template<typename T> void __declspec(dllexport) funcTmplDecl2(); + +// Export function template definition. +template<typename T> __declspec(dllexport) void funcTmplDef() {} + +// Export inline function template. +template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {} +template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {} + +template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl(); +template<typename T> void inlineFuncTmplDecl() {} + +template<typename T> __declspec(dllexport) void inlineFuncTmplDef(); +template<typename T> inline void inlineFuncTmplDef() {} + +// Redeclarations +template<typename T> __declspec(dllexport) void funcTmplRedecl1(); +template<typename T> __declspec(dllexport) void funcTmplRedecl1() {} + +template<typename T> __declspec(dllexport) void funcTmplRedecl2(); +template<typename T> void funcTmplRedecl2() {} + +template<typename T> void funcTmplRedecl3(); // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}} + +template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllexport' attribute}} + +// Function template friends +struct FuncTmplFriend { + template<typename T> friend __declspec(dllexport) void funcTmplFriend1(); + template<typename T> friend __declspec(dllexport) void funcTmplFriend2(); + template<typename T> friend void funcTmplFriend3(); // expected-note{{previous declaration is here}} + template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}} +}; +template<typename T> __declspec(dllexport) void funcTmplFriend1() {} +template<typename T> void funcTmplFriend2() {} +template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllexport' attribute}} + +// External linkage is required. +template<typename T> __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}} +template<typename T> __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}} +namespace { template<typename T> __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllexport'}} +namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl(); } + + +template<typename T> void funcTmpl() {} +template<typename T> __declspec(dllexport) void exportedFuncTmplDecl(); +template<typename T> __declspec(dllexport) void exportedFuncTmpl() {} + +// Export implicit instantiation of an exported function template. +void useFunTmplDecl() { exportedFuncTmplDecl<ImplicitInst_Exported>(); } +void useFunTmplDef() { exportedFuncTmpl<ImplicitInst_Exported>(); } + +// Export explicit instantiation declaration of an exported function template. +extern template void exportedFuncTmpl<ExplicitDecl_Exported>(); + template void exportedFuncTmpl<ExplicitDecl_Exported>(); + +// Export explicit instantiation definition of an exported function template. +template void exportedFuncTmpl<ExplicitInst_Exported>(); + +// Export specialization of an exported function template. +template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Exported>(); +template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {} + +// Not exporting specialization of an exported function template without +// explicit dllexport. +template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {} + + +// Export explicit instantiation declaration of a non-exported function template. +extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>(); + template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>(); + +// Export explicit instantiation definition of a non-exported function template. +template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>(); + +// Export specialization of a non-exported function template. +template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Exported>(); +template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {} + + + +//===----------------------------------------------------------------------===// +// Classes +//===----------------------------------------------------------------------===// + +class __declspec(dllexport) ClassDecl; + +class __declspec(dllexport) ClassDef {}; + +#ifdef MS +// expected-warning@+3{{'dllexport' attribute ignored}} +#endif +template <typename T> struct PartiallySpecializedClassTemplate {}; +template <typename T> struct __declspec(dllexport) PartiallySpecializedClassTemplate<T*> { void f() {} }; + +template <typename T> struct ExpliciallySpecializedClassTemplate {}; +template <> struct __declspec(dllexport) ExpliciallySpecializedClassTemplate<int> { void f() {} }; + + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template <typename T> class ClassTemplate {}; +template <typename T> class __declspec(dllexport) ExportedClassTemplate {}; +template <typename T> class __declspec(dllimport) ImportedClassTemplate {}; + +template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlySpecializedTemplate<int>' was explicitly specialized here}} +#endif +template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; + +template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlyInstantiatedTemplate<int>' was instantiated here}} +#endif +template struct ExplicitlyInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; + +// ClassTemplate<int> gets exported. +class __declspec(dllexport) DerivedFromTemplate : public ClassTemplate<int> {}; + +// ClassTemplate<int> is already exported. +class __declspec(dllexport) DerivedFromTemplate2 : public ClassTemplate<int> {}; + +// ExportedTemplate is explicitly exported. +class __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {}; + +// ImportedTemplate is explicitly imported. +class __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate<double>' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template without dll attribute is not supported}} +// expected-note@+3{{attribute is here}} +#endif +class DerivedFromTemplateD : public ClassTemplate<double> {}; +class __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate<bool>' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template with different dll attribute is not supported}} +// expected-note@+3{{attribute is here}} +#endif +class __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> {}; +class __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> {}; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to explicitly specialized base class template without dll attribute is not supported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {}; + +// Base class alredy specialized with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {}; + +// Base class already specialized with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to already instantiated base class template without dll attribute is not supported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; + +// Base class already instantiated with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {}; + +// Base class already instantiated with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; + + +//===----------------------------------------------------------------------===// +// Precedence +//===----------------------------------------------------------------------===// + +// dllexport takes precedence over dllimport if both are specified. +__attribute__((dllimport, dllexport)) extern int PrecedenceExternGlobal1A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllimport) __declspec(dllexport) extern int PrecedenceExternGlobal1B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllexport, dllimport)) extern int PrecedenceExternGlobal2A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) __declspec(dllimport) extern int PrecedenceExternGlobal2B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // expected-warning{{'dllimport' attribute ignored}} + +__declspec(dllexport) extern int PrecedenceExternGlobalRedecl1; +__declspec(dllimport) extern int PrecedenceExternGlobalRedecl1; // expected-warning{{'dllimport' attribute ignored}} + +__declspec(dllimport) extern int PrecedenceExternGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) extern int PrecedenceExternGlobalRedecl2; + +__declspec(dllexport) extern int PrecedenceGlobalRedecl1; +__declspec(dllimport) int PrecedenceGlobalRedecl1; // expected-warning{{'dllimport' attribute ignored}} + +__declspec(dllimport) extern int PrecedenceGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) int PrecedenceGlobalRedecl2; + +void __attribute__((dllimport, dllexport)) precedence1A() {} // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllimport) __declspec(dllexport) precedence1B() {} // expected-warning{{'dllimport' attribute ignored}} + +void __attribute__((dllexport, dllimport)) precedence2A() {} // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllexport) __declspec(dllimport) precedence2B() {} // expected-warning{{'dllimport' attribute ignored}} + +void __declspec(dllimport) precedenceRedecl1(); // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllexport) precedenceRedecl1() {} + +void __declspec(dllexport) precedenceRedecl2(); +void __declspec(dllimport) precedenceRedecl2() {} // expected-warning{{'dllimport' attribute ignored}} + + + +//===----------------------------------------------------------------------===// +// Class members +//===----------------------------------------------------------------------===// + +// Export individual members of a class. +struct ExportMembers { + struct Nested { + __declspec(dllexport) void normalDef(); + }; + + __declspec(dllexport) void normalDecl(); + __declspec(dllexport) void normalDef(); + __declspec(dllexport) void normalInclass() {} + __declspec(dllexport) void normalInlineDef(); + __declspec(dllexport) inline void normalInlineDecl(); + __declspec(dllexport) virtual void virtualDecl(); + __declspec(dllexport) virtual void virtualDef(); + __declspec(dllexport) virtual void virtualInclass() {} + __declspec(dllexport) virtual void virtualInlineDef(); + __declspec(dllexport) virtual inline void virtualInlineDecl(); + __declspec(dllexport) static void staticDecl(); + __declspec(dllexport) static void staticDef(); + __declspec(dllexport) static void staticInclass() {} + __declspec(dllexport) static void staticInlineDef(); + __declspec(dllexport) static inline void staticInlineDecl(); + +protected: + __declspec(dllexport) void protectedDef(); +private: + __declspec(dllexport) void privateDef(); +public: + + __declspec(dllexport) int Field; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static int StaticFieldDef; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) static const int StaticConstFieldDef; + __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllexport) constexpr static int ConstexprField = 1; + __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; +}; + + void ExportMembers::Nested::normalDef() {} + void ExportMembers::normalDef() {} +inline void ExportMembers::normalInlineDef() {} + void ExportMembers::normalInlineDecl() {} + void ExportMembers::virtualDef() {} +inline void ExportMembers::virtualInlineDef() {} + void ExportMembers::virtualInlineDecl() {} + void ExportMembers::staticDef() {} +inline void ExportMembers::staticInlineDef() {} + void ExportMembers::staticInlineDecl() {} + void ExportMembers::protectedDef() {} + void ExportMembers::privateDef() {} + + int ExportMembers::StaticFieldDef; +const int ExportMembers::StaticConstFieldDef = 1; +constexpr int ExportMembers::ConstexprFieldDef; + + +// Export on member definitions. +struct ExportMemberDefs { + __declspec(dllexport) void normalDef(); + __declspec(dllexport) void normalInlineDef(); + __declspec(dllexport) inline void normalInlineDecl(); + __declspec(dllexport) virtual void virtualDef(); + __declspec(dllexport) virtual void virtualInlineDef(); + __declspec(dllexport) virtual inline void virtualInlineDecl(); + __declspec(dllexport) static void staticDef(); + __declspec(dllexport) static void staticInlineDef(); + __declspec(dllexport) static inline void staticInlineDecl(); + + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) constexpr static int ConstexprField = 1; +}; + +__declspec(dllexport) void ExportMemberDefs::normalDef() {} +__declspec(dllexport) inline void ExportMemberDefs::normalInlineDef() {} +__declspec(dllexport) void ExportMemberDefs::normalInlineDecl() {} +__declspec(dllexport) void ExportMemberDefs::virtualDef() {} +__declspec(dllexport) inline void ExportMemberDefs::virtualInlineDef() {} +__declspec(dllexport) void ExportMemberDefs::virtualInlineDecl() {} +__declspec(dllexport) void ExportMemberDefs::staticDef() {} +__declspec(dllexport) inline void ExportMemberDefs::staticInlineDef() {} +__declspec(dllexport) void ExportMemberDefs::staticInlineDecl() {} + +__declspec(dllexport) int ExportMemberDefs::StaticField; +__declspec(dllexport) const int ExportMemberDefs::StaticConstField = 1; +__declspec(dllexport) constexpr int ExportMemberDefs::ConstexprField; + + +// Export special member functions. +struct ExportSpecials { + __declspec(dllexport) ExportSpecials() {} + __declspec(dllexport) ~ExportSpecials(); + __declspec(dllexport) inline ExportSpecials(const ExportSpecials&); + __declspec(dllexport) ExportSpecials& operator=(const ExportSpecials&); + __declspec(dllexport) ExportSpecials(ExportSpecials&&); + __declspec(dllexport) ExportSpecials& operator=(ExportSpecials&&); +}; + +ExportSpecials::~ExportSpecials() {} +ExportSpecials::ExportSpecials(const ExportSpecials&) {} +inline ExportSpecials& ExportSpecials::operator=(const ExportSpecials&) { return *this; } +ExportSpecials::ExportSpecials(ExportSpecials&&) {} +ExportSpecials& ExportSpecials::operator=(ExportSpecials&&) { return *this; } + + +// Export allocation functions. +extern "C" void* malloc(__SIZE_TYPE__ size); +extern "C" void free(void* p); +struct ExportAlloc { + __declspec(dllexport) void* operator new(__SIZE_TYPE__); + __declspec(dllexport) void* operator new[](__SIZE_TYPE__); + __declspec(dllexport) void operator delete(void*); + __declspec(dllexport) void operator delete[](void*); +}; +void* ExportAlloc::operator new(__SIZE_TYPE__ n) { return malloc(n); } +void* ExportAlloc::operator new[](__SIZE_TYPE__ n) { return malloc(n); } +void ExportAlloc::operator delete(void* p) { free(p); } +void ExportAlloc::operator delete[](void* p) { free(p); } + + +// Export deleted member functions. +struct ExportDeleted { + __declspec(dllexport) ExportDeleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ~ExportDeleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted(const ExportDeleted&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted& operator=(const ExportDeleted&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted(ExportDeleted&&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) ExportDeleted& operator=(ExportDeleted&&) = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} + __declspec(dllexport) void deleted() = delete; // expected-error{{attribute 'dllexport' cannot be applied to a deleted function}} +}; + + +// Export defaulted member functions. +struct ExportDefaulted { + __declspec(dllexport) ExportDefaulted() = default; + __declspec(dllexport) ~ExportDefaulted() = default; + __declspec(dllexport) ExportDefaulted(const ExportDefaulted&) = default; + __declspec(dllexport) ExportDefaulted& operator=(const ExportDefaulted&) = default; + __declspec(dllexport) ExportDefaulted(ExportDefaulted&&) = default; + __declspec(dllexport) ExportDefaulted& operator=(ExportDefaulted&&) = default; +}; + + +// Export defaulted member function definitions. +struct ExportDefaultedDefs { + __declspec(dllexport) ExportDefaultedDefs(); + __declspec(dllexport) ~ExportDefaultedDefs(); + + __declspec(dllexport) inline ExportDefaultedDefs(const ExportDefaultedDefs&); + __declspec(dllexport) ExportDefaultedDefs& operator=(const ExportDefaultedDefs&); + + __declspec(dllexport) ExportDefaultedDefs(ExportDefaultedDefs&&); + __declspec(dllexport) ExportDefaultedDefs& operator=(ExportDefaultedDefs&&); +}; + +// Export definitions. +__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs() = default; +ExportDefaultedDefs::~ExportDefaultedDefs() = default; + +// Export inline declaration and definition. +__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(const ExportDefaultedDefs&) = default; +inline ExportDefaultedDefs& ExportDefaultedDefs::operator=(const ExportDefaultedDefs&) = default; + +__declspec(dllexport) ExportDefaultedDefs::ExportDefaultedDefs(ExportDefaultedDefs&&) = default; +ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default; + + +// Redeclarations cannot add dllexport. +struct MemberRedecl { + void normalDef(); // expected-note{{previous declaration is here}} + void normalInlineDef(); // expected-note{{previous declaration is here}} + inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + virtual void virtualDef(); // expected-note{{previous declaration is here}} + virtual void virtualInlineDef(); // expected-note{{previous declaration is here}} + virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}} + static void staticDef(); // expected-note{{previous declaration is here}} + static void staticInlineDef(); // expected-note{{previous declaration is here}} + static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +}; + +__declspec(dllexport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllexport' attribute}} +__declspec(dllexport) inline void MemberRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDef' cannot add 'dllexport' attribute}} +__declspec(dllexport) void MemberRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDecl' cannot add 'dllexport' attribute}} +__declspec(dllexport) void MemberRedecl::virtualDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualDef' cannot add 'dllexport' attribute}} +__declspec(dllexport) inline void MemberRedecl::virtualInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDef' cannot add 'dllexport' attribute}} +__declspec(dllexport) void MemberRedecl::virtualInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDecl' cannot add 'dllexport' attribute}} +__declspec(dllexport) void MemberRedecl::staticDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticDef' cannot add 'dllexport' attribute}} +__declspec(dllexport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllexport' attribute}} +__declspec(dllexport) void MemberRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} + +__declspec(dllexport) int MemberRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticField' cannot add 'dllexport' attribute}} +__declspec(dllexport) const int MemberRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 'dllexport' attribute}} +__declspec(dllexport) constexpr int MemberRedecl::ConstexprField; // expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllexport' attribute}} + + + +//===----------------------------------------------------------------------===// +// Class member templates +//===----------------------------------------------------------------------===// + +struct ExportMemberTmpl { + template<typename T> __declspec(dllexport) void normalDecl(); + template<typename T> __declspec(dllexport) void normalDef(); + template<typename T> __declspec(dllexport) void normalInclass() {} + template<typename T> __declspec(dllexport) void normalInlineDef(); + template<typename T> __declspec(dllexport) inline void normalInlineDecl(); + template<typename T> __declspec(dllexport) static void staticDecl(); + template<typename T> __declspec(dllexport) static void staticDef(); + template<typename T> __declspec(dllexport) static void staticInclass() {} + template<typename T> __declspec(dllexport) static void staticInlineDef(); + template<typename T> __declspec(dllexport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template<typename T> __declspec(dllexport) static int StaticField; + template<typename T> __declspec(dllexport) static int StaticFieldDef; + template<typename T> __declspec(dllexport) static const int StaticConstField; + template<typename T> __declspec(dllexport) static const int StaticConstFieldDef; + template<typename T> __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + template<typename T> __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + template<typename T> __declspec(dllexport) constexpr static int ConstexprField = 1; + template<typename T> __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> void ExportMemberTmpl::normalDef() {} +template<typename T> inline void ExportMemberTmpl::normalInlineDef() {} +template<typename T> void ExportMemberTmpl::normalInlineDecl() {} +template<typename T> void ExportMemberTmpl::staticDef() {} +template<typename T> inline void ExportMemberTmpl::staticInlineDef() {} +template<typename T> void ExportMemberTmpl::staticInlineDecl() {} + +#if __has_feature(cxx_variable_templates) +template<typename T> int ExportMemberTmpl::StaticFieldDef; +template<typename T> const int ExportMemberTmpl::StaticConstFieldDef = 1; +template<typename T> constexpr int ExportMemberTmpl::ConstexprFieldDef; +#endif // __has_feature(cxx_variable_templates) + + +// Redeclarations cannot add dllexport. +struct MemTmplRedecl { + template<typename T> void normalDef(); // expected-note{{previous declaration is here}} + template<typename T> void normalInlineDef(); // expected-note{{previous declaration is here}} + template<typename T> inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + template<typename T> static void staticDef(); // expected-note{{previous declaration is here}} + template<typename T> static void staticInlineDef(); // expected-note{{previous declaration is here}} + template<typename T> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template<typename T> static int StaticField; // expected-note{{previous declaration is here}} + template<typename T> static const int StaticConstField; // expected-note{{previous declaration is here}} + template<typename T> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> __declspec(dllexport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} + +#if __has_feature(cxx_variable_templates) +template<typename T> __declspec(dllexport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} +#endif // __has_feature(cxx_variable_templates) + + + +struct MemFunTmpl { + template<typename T> void normalDef() {} + template<typename T> __declspec(dllexport) void exportedNormal() {} + template<typename T> static void staticDef() {} + template<typename T> __declspec(dllexport) static void exportedStatic() {} +}; + +// Export implicit instantiation of an exported member function template. +void useMemFunTmpl() { + MemFunTmpl().exportedNormal<ImplicitInst_Exported>(); + MemFunTmpl().exportedStatic<ImplicitInst_Exported>(); +} + +// Export explicit instantiation declaration of an exported member function +// template. +extern template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>(); + template void MemFunTmpl::exportedNormal<ExplicitDecl_Exported>(); + +extern template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>(); + template void MemFunTmpl::exportedStatic<ExplicitDecl_Exported>(); + +// Export explicit instantiation definition of an exported member function +// template. +template void MemFunTmpl::exportedNormal<ExplicitInst_Exported>(); +template void MemFunTmpl::exportedStatic<ExplicitInst_Exported>(); + +// Export specialization of an exported member function template. +template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Exported>(); +template<> __declspec(dllexport) void MemFunTmpl::exportedNormal<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void MemFunTmpl::exportedNormal<ExplicitSpec_InlineDef_Exported>() {} + +template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Exported>(); +template<> __declspec(dllexport) void MemFunTmpl::exportedStatic<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void MemFunTmpl::exportedStatic<ExplicitSpec_InlineDef_Exported>() {} + +// Not exporting specialization of an exported member function template without +// explicit dllexport. +template<> void MemFunTmpl::exportedNormal<ExplicitSpec_NotExported>() {} +template<> void MemFunTmpl::exportedStatic<ExplicitSpec_NotExported>() {} + + +// Export explicit instantiation declaration of a non-exported member function +// template. +extern template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>(); + template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitDecl_Exported>(); + +extern template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>(); + template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitDecl_Exported>(); + +// Export explicit instantiation definition of a non-exported member function +// template. +template __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitInst_Exported>(); +template __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitInst_Exported>(); + +// Export specialization of a non-exported member function template. +template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Exported>(); +template<> __declspec(dllexport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Exported>() {} + +template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Exported>(); +template<> __declspec(dllexport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Exported>() {} +template<> __declspec(dllexport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Exported>() {} + + + +#if __has_feature(cxx_variable_templates) +struct MemVarTmpl { + template<typename T> static const int StaticVar = 1; + template<typename T> __declspec(dllexport) static const int ExportedStaticVar = 1; +}; +template<typename T> const int MemVarTmpl::StaticVar; +template<typename T> const int MemVarTmpl::ExportedStaticVar; + +// Export implicit instantiation of an exported member variable template. +int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; } + +// Export explicit instantiation declaration of an exported member variable +// template. +extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; + template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of an exported member variable +// template. +template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>; + +// Export specialization of an exported member variable template. +template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Exported>; +template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1; + +// Not exporting specialization of an exported member variable template without +// explicit dllexport. +template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported>; + + +// Export explicit instantiation declaration of a non-exported member variable +// template. +extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; + template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>; + +// Export explicit instantiation definition of a non-exported member variable +// template. +template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>; + +// Export specialization of a non-exported member variable template. +template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Exported>; +template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 1; + +#endif // __has_feature(cxx_variable_templates) + + + +//===----------------------------------------------------------------------===// +// Class template members +//===----------------------------------------------------------------------===// + +// Export individual members of a class template. +template<typename T> +struct ExportClassTmplMembers { + __declspec(dllexport) void normalDecl(); + __declspec(dllexport) void normalDef(); + __declspec(dllexport) void normalInclass() {} + __declspec(dllexport) void normalInlineDef(); + __declspec(dllexport) inline void normalInlineDecl(); + __declspec(dllexport) virtual void virtualDecl(); + __declspec(dllexport) virtual void virtualDef(); + __declspec(dllexport) virtual void virtualInclass() {} + __declspec(dllexport) virtual void virtualInlineDef(); + __declspec(dllexport) virtual inline void virtualInlineDecl(); + __declspec(dllexport) static void staticDecl(); + __declspec(dllexport) static void staticDef(); + __declspec(dllexport) static void staticInclass() {} + __declspec(dllexport) static void staticInlineDef(); + __declspec(dllexport) static inline void staticInlineDecl(); + +protected: + __declspec(dllexport) void protectedDef(); +private: + __declspec(dllexport) void privateDef(); +public: + + __declspec(dllexport) int Field; // expected-warning{{'dllexport' attribute only applies to variables, functions and classes}} + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static int StaticFieldDef; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) static const int StaticConstFieldDef; + __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllexport) constexpr static int ConstexprField = 1; + __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; +}; + +template<typename T> void ExportClassTmplMembers<T>::normalDef() {} +template<typename T> inline void ExportClassTmplMembers<T>::normalInlineDef() {} +template<typename T> void ExportClassTmplMembers<T>::normalInlineDecl() {} +template<typename T> void ExportClassTmplMembers<T>::virtualDef() {} +template<typename T> inline void ExportClassTmplMembers<T>::virtualInlineDef() {} +template<typename T> void ExportClassTmplMembers<T>::virtualInlineDecl() {} +template<typename T> void ExportClassTmplMembers<T>::staticDef() {} +template<typename T> inline void ExportClassTmplMembers<T>::staticInlineDef() {} +template<typename T> void ExportClassTmplMembers<T>::staticInlineDecl() {} +template<typename T> void ExportClassTmplMembers<T>::protectedDef() {} +template<typename T> void ExportClassTmplMembers<T>::privateDef() {} + +template<typename T> int ExportClassTmplMembers<T>::StaticFieldDef; +template<typename T> const int ExportClassTmplMembers<T>::StaticConstFieldDef = 1; +template<typename T> constexpr int ExportClassTmplMembers<T>::ConstexprFieldDef; + +template struct ExportClassTmplMembers<ImplicitInst_Exported>; + + +// Redeclarations cannot add dllexport. +template<typename T> +struct CTMR /*ClassTmplMemberRedecl*/ { + void normalDef(); // expected-note{{previous declaration is here}} + void normalInlineDef(); // expected-note{{previous declaration is here}} + inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + virtual void virtualDef(); // expected-note{{previous declaration is here}} + virtual void virtualInlineDef(); // expected-note{{previous declaration is here}} + virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}} + static void staticDef(); // expected-note{{previous declaration is here}} + static void staticInlineDef(); // expected-note{{previous declaration is here}} + static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +}; + +template<typename T> __declspec(dllexport) void CTMR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void CTMR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void CTMR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void CTMR<T>::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void CTMR<T>::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void CTMR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void CTMR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) void CTMR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}} + +template<typename T> __declspec(dllexport) int CTMR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) const int CTMR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) constexpr int CTMR<T>::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} + + + +//===----------------------------------------------------------------------===// +// Class template member templates +//===----------------------------------------------------------------------===// + +template<typename T> +struct ExportClsTmplMemTmpl { + template<typename U> __declspec(dllexport) void normalDecl(); + template<typename U> __declspec(dllexport) void normalDef(); + template<typename U> __declspec(dllexport) void normalInclass() {} + template<typename U> __declspec(dllexport) void normalInlineDef(); + template<typename U> __declspec(dllexport) inline void normalInlineDecl(); + template<typename U> __declspec(dllexport) static void staticDecl(); + template<typename U> __declspec(dllexport) static void staticDef(); + template<typename U> __declspec(dllexport) static void staticInclass() {} + template<typename U> __declspec(dllexport) static void staticInlineDef(); + template<typename U> __declspec(dllexport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template<typename U> __declspec(dllexport) static int StaticField; + template<typename U> __declspec(dllexport) static int StaticFieldDef; + template<typename U> __declspec(dllexport) static const int StaticConstField; + template<typename U> __declspec(dllexport) static const int StaticConstFieldDef; + template<typename U> __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + template<typename U> __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + template<typename U> __declspec(dllexport) constexpr static int ConstexprField = 1; + template<typename U> __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::normalDef() {} +template<typename T> template<typename U> inline void ExportClsTmplMemTmpl<T>::normalInlineDef() {} +template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::normalInlineDecl() {} +template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::staticDef() {} +template<typename T> template<typename U> inline void ExportClsTmplMemTmpl<T>::staticInlineDef() {} +template<typename T> template<typename U> void ExportClsTmplMemTmpl<T>::staticInlineDecl() {} + +#if __has_feature(cxx_variable_templates) +template<typename T> template<typename U> int ExportClsTmplMemTmpl<T>::StaticFieldDef; +template<typename T> template<typename U> const int ExportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; +template<typename T> template<typename U> constexpr int ExportClsTmplMemTmpl<T>::ConstexprFieldDef; +#endif // __has_feature(cxx_variable_templates) + + +// Redeclarations cannot add dllexport. +template<typename T> +struct CTMTR /*ClassTmplMemberTmplRedecl*/ { + template<typename U> void normalDef(); // expected-note{{previous declaration is here}} + template<typename U> void normalInlineDef(); // expected-note{{previous declaration is here}} + template<typename U> inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + template<typename U> static void staticDef(); // expected-note{{previous declaration is here}} + template<typename U> static void staticInlineDef(); // expected-note{{previous declaration is here}} + template<typename U> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template<typename U> static int StaticField; // expected-note{{previous declaration is here}} + template<typename U> static const int StaticConstField; // expected-note{{previous declaration is here}} + template<typename U> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) void CTMTR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}} + +#if __has_feature(cxx_variable_templates) +template<typename T> template<typename U> __declspec(dllexport) int CTMTR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) const int CTMTR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}} +template<typename T> template<typename U> __declspec(dllexport) constexpr int CTMTR<T>::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} +#endif // __has_feature(cxx_variable_templates) + +// FIXME: Precedence rules seem to be different for classes. diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp new file mode 100644 index 0000000000000..8e826f7ae6bfc --- /dev/null +++ b/test/SemaCXX/dllimport.cpp @@ -0,0 +1,1085 @@ +// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 -DMS %s +// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y -DMS %s +// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Imported {}; +struct ExplicitDecl_Imported {}; +struct ExplicitInst_Imported {}; +struct ExplicitSpec_Imported {}; +struct ExplicitSpec_Def_Imported {}; +struct ExplicitSpec_InlineDef_Imported {}; +struct ExplicitSpec_NotImported {}; +namespace { struct Internal {}; } + + +// Invalid usage. +__declspec(dllimport) typedef int typedef1; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllimport) int typedef2; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +typedef int __declspec(dllimport) typedef3; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +typedef __declspec(dllimport) void (*FunTy)(); // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +enum __declspec(dllimport) Enum {}; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +#if __has_feature(cxx_strong_enums) + enum class __declspec(dllimport) EnumClass {}; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} +#endif + + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Import declaration. +__declspec(dllimport) extern int ExternGlobalDecl; + +// dllimport implies a declaration. +__declspec(dllimport) int GlobalDecl; +int **__attribute__((dllimport))* GlobalDeclChunkAttr; +int GlobalDeclAttr __attribute__((dllimport)); + +// Not allowed on definitions. +__declspec(dllimport) extern int ExternGlobalInit = 1; // expected-error{{definition of dllimport data}} +__declspec(dllimport) int GlobalInit1 = 1; // expected-error{{definition of dllimport data}} +int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}} + +// Declare, then reject definition. +__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +// Redeclarations +__declspec(dllimport) extern int GlobalRedecl1; +__declspec(dllimport) extern int GlobalRedecl1; + +__declspec(dllimport) int GlobalRedecl2a; +__declspec(dllimport) int GlobalRedecl2a; + +int *__attribute__((dllimport)) GlobalRedecl2b; +int *__attribute__((dllimport)) GlobalRedecl2b; + +int GlobalRedecl2c __attribute__((dllimport)); +int GlobalRedecl2c __attribute__((dllimport)); + +// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC +// and drop the dllimport with a warning. +__declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + + extern int GlobalRedecl4; // expected-note{{previous declaration is here}} +__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} + +// External linkage is required. +__declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}} +__declspec(dllimport) Internal InternalTypeGlobal; // expected-error{{'InternalTypeGlobal' must have external linkage when declared 'dllimport'}} +namespace { __declspec(dllimport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllimport'}} +namespace ns { __declspec(dllimport) int ExternalGlobal; } + +__declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllimport'}} + // expected-error@-1{{definition of dllimport data}} + +// Import in local scope. +__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}} +__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}} +__declspec(dllimport) float LocalRedecl3; // expected-note{{previous definition is here}} +void functionScope() { + __declspec(dllimport) int LocalRedecl1; // expected-error{{redefinition of 'LocalRedecl1' with a different type: 'int' vs 'float'}} + int *__attribute__((dllimport)) LocalRedecl2; // expected-error{{redefinition of 'LocalRedecl2' with a different type: 'int *' vs 'float'}} + int LocalRedecl3 __attribute__((dllimport)); // expected-error{{redefinition of 'LocalRedecl3' with a different type: 'int' vs 'float'}} + + __declspec(dllimport) int LocalVarDecl; + __declspec(dllimport) int LocalVarDef = 1; // expected-error{{definition of dllimport data}} + __declspec(dllimport) extern int ExternLocalVarDecl; + __declspec(dllimport) extern int ExternLocalVarDef = 1; // expected-error{{definition of dllimport data}} + __declspec(dllimport) static int StaticLocalVar; // expected-error{{'StaticLocalVar' must have external linkage when declared 'dllimport'}} +} + + + +//===----------------------------------------------------------------------===// +// Variable templates +//===----------------------------------------------------------------------===// +#if __has_feature(cxx_variable_templates) + +// Import declaration. +template<typename T> __declspec(dllimport) extern int ExternVarTmplDecl; + +// dllimport implies a declaration. +template<typename T> __declspec(dllimport) int VarTmplDecl; + +// Not allowed on definitions. +template<typename T> __declspec(dllimport) extern int ExternVarTmplInit = 1; // expected-error{{definition of dllimport data}} +template<typename T> __declspec(dllimport) int VarTmplInit1 = 1; // expected-error{{definition of dllimport data}} +template<typename T> int __declspec(dllimport) VarTmplInit2 = 1; // expected-error{{definition of dllimport data}} + +// Declare, then reject definition. +template<typename T> __declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +template<typename T> int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +template<typename T> __declspec(dllimport) int VarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +template<typename T> int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +// Redeclarations +template<typename T> __declspec(dllimport) extern int VarTmplRedecl1; +template<typename T> __declspec(dllimport) extern int VarTmplRedecl1; + +template<typename T> __declspec(dllimport) int VarTmplRedecl2; +template<typename T> __declspec(dllimport) int VarTmplRedecl2; + +template<typename T> __declspec(dllimport) extern int VarTmplRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +template<typename T> extern int VarTmplRedecl3; // expected-warning{{'VarTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +template<typename T> extern int VarTmplRedecl4; // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllimport) extern int VarTmplRedecl4; // expected-error{{redeclaration of 'VarTmplRedecl4' cannot add 'dllimport' attribute}} + +// External linkage is required. +template<typename T> __declspec(dllimport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllimport'}} +template<typename T> __declspec(dllimport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllimport'}} +namespace { template<typename T> __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllimport'}} +namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; } + +template<typename T> __declspec(dllimport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{definition of dllimport data}} // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllimport'}} + + +template<typename T> int VarTmpl; +template<typename T> __declspec(dllimport) int ImportedVarTmpl; + +// Import implicit instantiation of an imported variable template. +int useVarTmpl() { return ImportedVarTmpl<ImplicitInst_Imported>; } + +// Import explicit instantiation declaration of an imported variable template. +extern template int ImportedVarTmpl<ExplicitDecl_Imported>; + +// An explicit instantiation definition of an imported variable template cannot +// be imported because the template must be defined which is illegal. + +// Import specialization of an imported variable template. +template<> __declspec(dllimport) int ImportedVarTmpl<ExplicitSpec_Imported>; +template<> __declspec(dllimport) int ImportedVarTmpl<ExplicitSpec_Def_Imported> = 1; // expected-error{{definition of dllimport data}} + +// Not importing specialization of an imported variable template without +// explicit dllimport. +template<> int ImportedVarTmpl<ExplicitSpec_NotImported>; + + +// Import explicit instantiation declaration of a non-imported variable template. +extern template __declspec(dllimport) int VarTmpl<ExplicitDecl_Imported>; + +// Import explicit instantiation definition of a non-imported variable template. +template __declspec(dllimport) int VarTmpl<ExplicitInst_Imported>; + +// Import specialization of a non-imported variable template. +template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Imported>; +template<> __declspec(dllimport) int VarTmpl<ExplicitSpec_Def_Imported> = 1; // expected-error{{definition of dllimport data}} + +#endif // __has_feature(cxx_variable_templates) + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Import function declaration. Check different placements. +__attribute__((dllimport)) void decl1A(); // Sanity check with __attribute__ +__declspec(dllimport) void decl1B(); + +void __attribute__((dllimport)) decl2A(); +void __declspec(dllimport) decl2B(); + +// Not allowed on function definitions. +__declspec(dllimport) void def() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} + +// extern "C" +extern "C" __declspec(dllimport) void externC(); + +// Import inline function. +__declspec(dllimport) inline void inlineFunc1() {} +inline void __attribute__((dllimport)) inlineFunc2() {} + +__declspec(dllimport) inline void inlineDecl(); + void inlineDecl() {} + +__declspec(dllimport) void inlineDef(); + inline void inlineDef() {} + +// Redeclarations +__declspec(dllimport) void redecl1(); +__declspec(dllimport) void redecl1(); + +// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC +// and drop the dllimport with a warning. +__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + + void redecl4(); // expected-note{{previous declaration is here}} +__declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} + + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllimport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllimport' attribute}} + +// Friend functions +struct FuncFriend { + friend __declspec(dllimport) void friend1(); + friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + friend void friend4(); // expected-note{{previous declaration is here}} + friend void friend5(); // expected-note{{previous declaration is here}} +}; +__declspec(dllimport) void friend1(); + void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +__declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'friend4' cannot add 'dllimport' attribute}} +__declspec(dllimport) inline void friend5() {} // expected-error{{redeclaration of 'friend5' cannot add 'dllimport' attribute}} + +// Implicit declarations can be redeclared with dllimport. +__declspec(dllimport) void* operator new(__SIZE_TYPE__ n); + +// External linkage is required. +__declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}} +__declspec(dllimport) Internal internalRetFunc(); // expected-error{{'internalRetFunc' must have external linkage when declared 'dllimport'}} +namespace { __declspec(dllimport) void internalFunc(); } // expected-error{{'(anonymous namespace)::internalFunc' must have external linkage when declared 'dllimport'}} +namespace ns { __declspec(dllimport) void externalFunc(); } + +// Import deleted functions. +// FIXME: Deleted functions are definitions so a missing inline is diagnosed +// here which is irrelevant. But because the delete keyword is parsed later +// there is currently no straight-forward way to avoid this diagnostic. +__declspec(dllimport) void deletedFunc() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} expected-error{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void deletedInlineFunc() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + + + +//===----------------------------------------------------------------------===// +// Function templates +//===----------------------------------------------------------------------===// + +// Import function template declaration. Check different placements. +template<typename T> __declspec(dllimport) void funcTmplDecl1(); +template<typename T> void __declspec(dllimport) funcTmplDecl2(); + +// Import function template definition. +template<typename T> __declspec(dllimport) void funcTmplDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} + +// Import inline function template. +template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {} +template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {} + +template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl(); +template<typename T> void inlineFuncTmplDecl() {} + +template<typename T> __declspec(dllimport) void inlineFuncTmplDef(); +template<typename T> inline void inlineFuncTmplDef() {} + +// Redeclarations +template<typename T> __declspec(dllimport) void funcTmplRedecl1(); +template<typename T> __declspec(dllimport) void funcTmplRedecl1(); + +template<typename T> __declspec(dllimport) void funcTmplRedecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +template<typename T> void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +template<typename T> __declspec(dllimport) void funcTmplRedecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +template<typename T> void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}} + +template<typename T> void funcTmplRedecl5(); // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5' cannot add 'dllimport' attribute}} + +// Function template friends +struct FuncTmplFriend { + template<typename T> friend __declspec(dllimport) void funcTmplFriend1(); + template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + template<typename T> friend __declspec(dllimport) void funcTmplFriend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}} + template<typename T> friend __declspec(dllimport) inline void funcTmplFriend5(); +}; +template<typename T> __declspec(dllimport) void funcTmplFriend1(); +template<typename T> void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}} +template<typename T> inline void funcTmplFriend5() {} + +// External linkage is required. +template<typename T> __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}} +template<typename T> __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllimport'}} +namespace { template<typename T> __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllimport'}} +namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); } + + +template<typename T> void funcTmpl() {} +template<typename T> inline void inlineFuncTmpl() {} +template<typename T> __declspec(dllimport) void importedFuncTmplDecl(); +template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {} + +// Import implicit instantiation of an imported function template. +void useFunTmplDecl() { importedFuncTmplDecl<ImplicitInst_Imported>(); } +void useFunTmplDef() { importedFuncTmpl<ImplicitInst_Imported>(); } + +// Import explicit instantiation declaration of an imported function template. +extern template void importedFuncTmpl<ExplicitDecl_Imported>(); + +// Import explicit instantiation definition of an imported function template. +// NB: MSVC fails this instantiation without explicit dllimport which is most +// likely a bug because an implicit instantiation is accepted. +template void importedFuncTmpl<ExplicitInst_Imported>(); + +// Import specialization of an imported function template. A definition must be +// declared inline. +template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} +template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {} + +// Not importing specialization of an imported function template without +// explicit dllimport. +template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {} + + +// Import explicit instantiation declaration of a non-imported function template. +extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>(); +extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>(); + +// Import explicit instantiation definition of a non-imported function template. +template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>(); +template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>(); + +// Import specialization of a non-imported function template. A definition must +// be declared inline. +template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} +template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} + + +//===----------------------------------------------------------------------===// +// Class members +//===----------------------------------------------------------------------===// + +// Import individual members of a class. +struct ImportMembers { + struct Nested { + __declspec(dllimport) void normalDecl(); + __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + }; + + __declspec(dllimport) void normalDecl(); + __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + __declspec(dllimport) void normalInclass() {} + __declspec(dllimport) void normalInlineDef(); + __declspec(dllimport) inline void normalInlineDecl(); + __declspec(dllimport) virtual void virtualDecl(); + __declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + __declspec(dllimport) virtual void virtualInclass() {} + __declspec(dllimport) virtual void virtualInlineDef(); + __declspec(dllimport) virtual inline void virtualInlineDecl(); + __declspec(dllimport) static void staticDecl(); + __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + __declspec(dllimport) static void staticInclass() {} + __declspec(dllimport) static void staticInlineDef(); + __declspec(dllimport) static inline void staticInlineDecl(); + +protected: + __declspec(dllimport) void protectedDecl(); +private: + __declspec(dllimport) void privateDecl(); +public: + + __declspec(dllimport) int Field; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllimport) constexpr static int ConstexprField = 1; + __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +}; + + void ImportMembers::Nested::normalDef() {} // expected-warning{{'ImportMembers::Nested::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + void ImportMembers::normalDef() {} // expected-warning{{'ImportMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +inline void ImportMembers::normalInlineDef() {} + void ImportMembers::normalInlineDecl() {} + void ImportMembers::virtualDef() {} // expected-warning{{'ImportMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +inline void ImportMembers::virtualInlineDef() {} + void ImportMembers::virtualInlineDecl() {} + void ImportMembers::staticDef() {} // expected-warning{{'ImportMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +inline void ImportMembers::staticInlineDef() {} + void ImportMembers::staticInlineDecl() {} + + int ImportMembers::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} +const int ImportMembers::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} +constexpr int ImportMembers::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} + + +// Import on member definitions. +struct ImportMemberDefs { + __declspec(dllimport) void normalDef(); + __declspec(dllimport) void normalInlineDef(); + __declspec(dllimport) inline void normalInlineDecl(); + __declspec(dllimport) virtual void virtualDef(); + __declspec(dllimport) virtual void virtualInlineDef(); + __declspec(dllimport) virtual inline void virtualInlineDecl(); + __declspec(dllimport) static void staticDef(); + __declspec(dllimport) static void staticInlineDef(); + __declspec(dllimport) static inline void staticInlineDecl(); + + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) constexpr static int ConstexprField = 1; +}; + +__declspec(dllimport) void ImportMemberDefs::normalDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void ImportMemberDefs::normalInlineDef() {} +__declspec(dllimport) void ImportMemberDefs::normalInlineDecl() {} +__declspec(dllimport) void ImportMemberDefs::virtualDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void ImportMemberDefs::virtualInlineDef() {} +__declspec(dllimport) void ImportMemberDefs::virtualInlineDecl() {} +__declspec(dllimport) void ImportMemberDefs::staticDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void ImportMemberDefs::staticInlineDef() {} +__declspec(dllimport) void ImportMemberDefs::staticInlineDecl() {} + +__declspec(dllimport) int ImportMemberDefs::StaticField; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}} +__declspec(dllimport) const int ImportMemberDefs::StaticConstField = 1; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}} +__declspec(dllimport) constexpr int ImportMemberDefs::ConstexprField; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}} + + +// Import special member functions. +struct ImportSpecials { + __declspec(dllimport) ImportSpecials(); + __declspec(dllimport) ~ImportSpecials(); + __declspec(dllimport) ImportSpecials(const ImportSpecials&); + __declspec(dllimport) ImportSpecials& operator=(const ImportSpecials&); + __declspec(dllimport) ImportSpecials(ImportSpecials&&); + __declspec(dllimport) ImportSpecials& operator=(ImportSpecials&&); +}; + + +// Import deleted member functions. +struct ImportDeleted { + __declspec(dllimport) ImportDeleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ~ImportDeleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted(const ImportDeleted&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted& operator=(const ImportDeleted&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted(ImportDeleted&&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) ImportDeleted& operator=(ImportDeleted&&) = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} + __declspec(dllimport) void deleted() = delete; // expected-error{{attribute 'dllimport' cannot be applied to a deleted function}} +}; + + +// Import allocation functions. +struct ImportAlloc { + __declspec(dllimport) void* operator new(__SIZE_TYPE__); + __declspec(dllimport) void* operator new[](__SIZE_TYPE__); + __declspec(dllimport) void operator delete(void*); + __declspec(dllimport) void operator delete[](void*); +}; + + +// Import defaulted member functions. +struct ImportDefaulted { + __declspec(dllimport) ImportDefaulted() = default; + __declspec(dllimport) ~ImportDefaulted() = default; + __declspec(dllimport) ImportDefaulted(const ImportDefaulted&) = default; + __declspec(dllimport) ImportDefaulted& operator=(const ImportDefaulted&) = default; + __declspec(dllimport) ImportDefaulted(ImportDefaulted&&) = default; + __declspec(dllimport) ImportDefaulted& operator=(ImportDefaulted&&) = default; +}; + + +// Import defaulted member function definitions. +struct ImportDefaultedDefs { + __declspec(dllimport) ImportDefaultedDefs(); + __declspec(dllimport) ~ImportDefaultedDefs(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + + __declspec(dllimport) inline ImportDefaultedDefs(const ImportDefaultedDefs&); + __declspec(dllimport) ImportDefaultedDefs& operator=(const ImportDefaultedDefs&); + + __declspec(dllimport) ImportDefaultedDefs(ImportDefaultedDefs&&); + __declspec(dllimport) ImportDefaultedDefs& operator=(ImportDefaultedDefs&&); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} +}; + +// Not allowed on definitions. +__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs() = default; // expected-error{{dllimport cannot be applied to non-inline function definition}} + +// dllimport cannot be dropped. +ImportDefaultedDefs::~ImportDefaultedDefs() = default; // expected-warning{{'ImportDefaultedDefs::~ImportDefaultedDefs' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + +// Import inline declaration and definition. +__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs(const ImportDefaultedDefs&) = default; +inline ImportDefaultedDefs& ImportDefaultedDefs::operator=(const ImportDefaultedDefs&) = default; + +__declspec(dllimport) ImportDefaultedDefs::ImportDefaultedDefs(ImportDefaultedDefs&&) = default; // expected-error{{dllimport cannot be applied to non-inline function definition}} +ImportDefaultedDefs& ImportDefaultedDefs::operator=(ImportDefaultedDefs&&) = default; // expected-warning{{'ImportDefaultedDefs::operator=' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + + +// Redeclarations cannot add dllimport. +struct MemberRedecl { + void normalDef(); // expected-note{{previous declaration is here}} + void normalInlineDef(); // expected-note{{previous declaration is here}} + inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + virtual void virtualDef(); // expected-note{{previous declaration is here}} + virtual void virtualInlineDef(); // expected-note{{previous declaration is here}} + virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}} + static void staticDef(); // expected-note{{previous declaration is here}} + static void staticInlineDef(); // expected-note{{previous declaration is here}} + static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +}; + +__declspec(dllimport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void MemberRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDef' cannot add 'dllimport' attribute}} +__declspec(dllimport) void MemberRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::normalInlineDecl' cannot add 'dllimport' attribute}} +__declspec(dllimport) void MemberRedecl::virtualDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void MemberRedecl::virtualInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDef' cannot add 'dllimport' attribute}} +__declspec(dllimport) void MemberRedecl::virtualInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::virtualInlineDecl' cannot add 'dllimport' attribute}} +__declspec(dllimport) void MemberRedecl::staticDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +__declspec(dllimport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllimport' attribute}} +__declspec(dllimport) void MemberRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDecl' cannot add 'dllimport' attribute}} + +__declspec(dllimport) int MemberRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +__declspec(dllimport) const int MemberRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +__declspec(dllimport) constexpr int MemberRedecl::ConstexprField; // expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + + + +//===----------------------------------------------------------------------===// +// Class member templates +//===----------------------------------------------------------------------===// + +struct ImportMemberTmpl { + template<typename T> __declspec(dllimport) void normalDecl(); + template<typename T> __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + template<typename T> __declspec(dllimport) void normalInclass() {} + template<typename T> __declspec(dllimport) void normalInlineDef(); + template<typename T> __declspec(dllimport) inline void normalInlineDecl(); + template<typename T> __declspec(dllimport) static void staticDecl(); + template<typename T> __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + template<typename T> __declspec(dllimport) static void staticInclass() {} + template<typename T> __declspec(dllimport) static void staticInlineDef(); + template<typename T> __declspec(dllimport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template<typename T> __declspec(dllimport) static int StaticField; + template<typename T> __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + template<typename T> __declspec(dllimport) static const int StaticConstField; + template<typename T> __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + template<typename T> __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + template<typename T> __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + template<typename T> __declspec(dllimport) constexpr static int ConstexprField = 1; + template<typename T> __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> inline void ImportMemberTmpl::normalInlineDef() {} +template<typename T> void ImportMemberTmpl::normalInlineDecl() {} +template<typename T> void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> inline void ImportMemberTmpl::staticInlineDef() {} +template<typename T> void ImportMemberTmpl::staticInlineDecl() {} + +#if __has_feature(cxx_variable_templates) +template<typename T> int ImportMemberTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} +template<typename T> const int ImportMemberTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} +template<typename T> constexpr int ImportMemberTmpl::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} +#endif // __has_feature(cxx_variable_templates) + + +// Redeclarations cannot add dllimport. +struct MemTmplRedecl { + template<typename T> void normalDef(); // expected-note{{previous declaration is here}} + template<typename T> void normalInlineDef(); // expected-note{{previous declaration is here}} + template<typename T> inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + template<typename T> static void staticDef(); // expected-note{{previous declaration is here}} + template<typename T> static void staticInlineDef(); // expected-note{{previous declaration is here}} + template<typename T> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template<typename T> static int StaticField; // expected-note{{previous declaration is here}} + template<typename T> static const int StaticConstField; // expected-note{{previous declaration is here}} + template<typename T> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> __declspec(dllimport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}} + +#if __has_feature(cxx_variable_templates) +template<typename T> __declspec(dllimport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template<typename T> __declspec(dllimport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template<typename T> __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) + + + +struct MemFunTmpl { + template<typename T> void normalDef() {} + template<typename T> __declspec(dllimport) void importedNormal() {} + template<typename T> static void staticDef() {} + template<typename T> __declspec(dllimport) static void importedStatic() {} +}; + +// Import implicit instantiation of an imported member function template. +void useMemFunTmpl() { + MemFunTmpl().importedNormal<ImplicitInst_Imported>(); + MemFunTmpl().importedStatic<ImplicitInst_Imported>(); +} + +// Import explicit instantiation declaration of an imported member function +// template. +extern template void MemFunTmpl::importedNormal<ExplicitDecl_Imported>(); +extern template void MemFunTmpl::importedStatic<ExplicitDecl_Imported>(); + +// Import explicit instantiation definition of an imported member function +// template. +// NB: MSVC fails this instantiation without explicit dllimport. +template void MemFunTmpl::importedNormal<ExplicitInst_Imported>(); +template void MemFunTmpl::importedStatic<ExplicitInst_Imported>(); + +// Import specialization of an imported member function template. +template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void MemFunTmpl::importedNormal<ExplicitSpec_Def_Imported>() {} // error on mingw +template<> __declspec(dllimport) inline void MemFunTmpl::importedNormal<ExplicitSpec_InlineDef_Imported>() {} +#ifndef MSABI +// expected-error@-3{{dllimport cannot be applied to non-inline function definition}} +#endif + +template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void MemFunTmpl::importedStatic<ExplicitSpec_Def_Imported>() {} // error on mingw +template<> __declspec(dllimport) inline void MemFunTmpl::importedStatic<ExplicitSpec_InlineDef_Imported>() {} +#ifndef MSABI +// expected-error@-3{{dllimport cannot be applied to non-inline function definition}} +#endif + +// Not importing specialization of an imported member function template without +// explicit dllimport. +template<> void MemFunTmpl::importedNormal<ExplicitSpec_NotImported>() {} +template<> void MemFunTmpl::importedStatic<ExplicitSpec_NotImported>() {} + + +// Import explicit instantiation declaration of a non-imported member function +// template. +extern template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitDecl_Imported>(); +extern template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitDecl_Imported>(); + +// Import explicit instantiation definition of a non-imported member function +// template. +template __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitInst_Imported>(); +template __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitInst_Imported>(); + +// Import specialization of a non-imported member function template. +template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void MemFunTmpl::normalDef<ExplicitSpec_Def_Imported>() {} // error on mingw +template<> __declspec(dllimport) inline void MemFunTmpl::normalDef<ExplicitSpec_InlineDef_Imported>() {} +#ifndef MSABI +// expected-error@-3{{dllimport cannot be applied to non-inline function definition}} +#endif + +template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void MemFunTmpl::staticDef<ExplicitSpec_Def_Imported>() {} // error on mingw +template<> __declspec(dllimport) inline void MemFunTmpl::staticDef<ExplicitSpec_InlineDef_Imported>() {} +#ifndef MSABI +// expected-error@-3{{dllimport cannot be applied to non-inline function definition}} +#endif + + + +#if __has_feature(cxx_variable_templates) +struct MemVarTmpl { + template<typename T> static const int StaticVar = 1; + template<typename T> __declspec(dllimport) static const int ImportedStaticVar = 1; +}; + +// Import implicit instantiation of an imported member variable template. +int useMemVarTmpl() { return MemVarTmpl::ImportedStaticVar<ImplicitInst_Imported>; } + +// Import explicit instantiation declaration of an imported member variable +// template. +extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>; + +// An explicit instantiation definition of an imported member variable template +// cannot be imported because the template must be defined which is illegal. The +// in-class initializer does not count. + +// Import specialization of an imported member variable template. +template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Imported>; +template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Def_Imported> = 1; + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + +// Not importing specialization of a member variable template without explicit +// dllimport. +template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>; + + +// Import explicit instantiation declaration of a non-imported member variable +// template. +extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>; + +// An explicit instantiation definition of a non-imported member variable template +// cannot be imported because the template must be defined which is illegal. The +// in-class initializer does not count. + +// Import specialization of a non-imported member variable template. +template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Imported>; +template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Imported> = 1; + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + +#endif // __has_feature(cxx_variable_templates) + + + +//===----------------------------------------------------------------------===// +// Class template members +//===----------------------------------------------------------------------===// + +// Import individual members of a class template. +template<typename T> +struct ImportClassTmplMembers { + __declspec(dllimport) void normalDecl(); + __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + __declspec(dllimport) void normalInclass() {} + __declspec(dllimport) void normalInlineDef(); + __declspec(dllimport) inline void normalInlineDecl(); + __declspec(dllimport) virtual void virtualDecl(); + __declspec(dllimport) virtual void virtualDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + __declspec(dllimport) virtual void virtualInclass() {} + __declspec(dllimport) virtual void virtualInlineDef(); + __declspec(dllimport) virtual inline void virtualInlineDecl(); + __declspec(dllimport) static void staticDecl(); + __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + __declspec(dllimport) static void staticInclass() {} + __declspec(dllimport) static void staticInlineDef(); + __declspec(dllimport) static inline void staticInlineDecl(); + +protected: + __declspec(dllimport) void protectedDecl(); +private: + __declspec(dllimport) void privateDecl(); +public: + + __declspec(dllimport) int Field; // expected-warning{{'dllimport' attribute only applies to variables, functions and classes}} + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllimport) constexpr static int ConstexprField = 1; + __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +}; + +// NB: MSVC is inconsistent here and disallows *InlineDef on class templates, +// but allows it on classes. We allow both. +template<typename T> void ImportClassTmplMembers<T>::normalDef() {} // expected-warning{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> inline void ImportClassTmplMembers<T>::normalInlineDef() {} +template<typename T> void ImportClassTmplMembers<T>::normalInlineDecl() {} +template<typename T> void ImportClassTmplMembers<T>::virtualDef() {} // expected-warning{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> inline void ImportClassTmplMembers<T>::virtualInlineDef() {} +template<typename T> void ImportClassTmplMembers<T>::virtualInlineDecl() {} +template<typename T> void ImportClassTmplMembers<T>::staticDef() {} // expected-warning{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> inline void ImportClassTmplMembers<T>::staticInlineDef() {} +template<typename T> void ImportClassTmplMembers<T>::staticInlineDecl() {} + +template<typename T> int ImportClassTmplMembers<T>::StaticFieldDef; // expected-warning{{definition of dllimport static field}} +template<typename T> const int ImportClassTmplMembers<T>::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} +template<typename T> constexpr int ImportClassTmplMembers<T>::ConstexprFieldDef; // expected-warning{{definition of dllimport static field}} + + +// Redeclarations cannot add dllimport. +template<typename T> +struct CTMR /*ClassTmplMemberRedecl*/ { + void normalDef(); // expected-note{{previous declaration is here}} + void normalInlineDef(); // expected-note{{previous declaration is here}} + inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + virtual void virtualDef(); // expected-note{{previous declaration is here}} + virtual void virtualInlineDef(); // expected-note{{previous declaration is here}} + virtual inline void virtualInlineDecl(); // expected-note{{previous declaration is here}} + static void staticDef(); // expected-note{{previous declaration is here}} + static void staticInlineDef(); // expected-note{{previous declaration is here}} + static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +}; + +template<typename T> __declspec(dllimport) void CTMR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void CTMR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void CTMR<T>::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void CTMR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}} +template<typename T> __declspec(dllimport) void CTMR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}} + +template<typename T> __declspec(dllimport) int CTMR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllimport' attribute}} + // expected-warning@-1{{definition of dllimport static field}} + // expected-note@-2{{attribute is here}} +template<typename T> __declspec(dllimport) const int CTMR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllimport' attribute}} + // expected-warning@-1{{definition of dllimport static field}} + // expected-note@-2{{attribute is here}} +template<typename T> __declspec(dllimport) constexpr int CTMR<T>::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}} + // expected-warning@-1{{definition of dllimport static field}} + // expected-note@-2{{attribute is here}} + + + +//===----------------------------------------------------------------------===// +// Class template member templates +//===----------------------------------------------------------------------===// + +template<typename T> +struct ImportClsTmplMemTmpl { + template<typename U> __declspec(dllimport) void normalDecl(); + template<typename U> __declspec(dllimport) void normalDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + template<typename U> __declspec(dllimport) void normalInclass() {} + template<typename U> __declspec(dllimport) void normalInlineDef(); + template<typename U> __declspec(dllimport) inline void normalInlineDecl(); + template<typename U> __declspec(dllimport) static void staticDecl(); + template<typename U> __declspec(dllimport) static void staticDef(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} + template<typename U> __declspec(dllimport) static void staticInclass() {} + template<typename U> __declspec(dllimport) static void staticInlineDef(); + template<typename U> __declspec(dllimport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template<typename U> __declspec(dllimport) static int StaticField; + template<typename U> __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + template<typename U> __declspec(dllimport) static const int StaticConstField; + template<typename U> __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + template<typename U> __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + template<typename U> __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + template<typename U> __declspec(dllimport) constexpr static int ConstexprField = 1; + template<typename U> __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::normalInlineDef() {} +template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::normalInlineDecl() {} +template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::staticInlineDef() {} +template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::staticInlineDecl() {} + +#if __has_feature(cxx_variable_templates) +template<typename T> template<typename U> int ImportClsTmplMemTmpl<T>::StaticFieldDef; // expected-warning{{definition of dllimport static field}} +template<typename T> template<typename U> const int ImportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} +template<typename T> template<typename U> constexpr int ImportClsTmplMemTmpl<T>::ConstexprFieldDef; // expected-warning{{definition of dllimport static field}} +#endif // __has_feature(cxx_variable_templates) + + +// Redeclarations cannot add dllimport. +template<typename T> +struct CTMTR /*ClassTmplMemberTmplRedecl*/ { + template<typename U> void normalDef(); // expected-note{{previous declaration is here}} + template<typename U> void normalInlineDef(); // expected-note{{previous declaration is here}} + template<typename U> inline void normalInlineDecl(); // expected-note{{previous declaration is here}} + template<typename U> static void staticDef(); // expected-note{{previous declaration is here}} + template<typename U> static void staticInlineDef(); // expected-note{{previous declaration is here}} + template<typename U> static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template<typename U> static int StaticField; // expected-note{{previous declaration is here}} + template<typename U> static const int StaticConstField; // expected-note{{previous declaration is here}} + template<typename U> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) +}; + +template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}} +template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllimport' attribute}} +template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllimport' attribute}} + // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} +template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}} +template<typename T> template<typename U> __declspec(dllimport) void CTMTR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}} + +#if __has_feature(cxx_variable_templates) +template<typename T> template<typename U> __declspec(dllimport) int CTMTR<T>::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllimport' attribute}} + // expected-warning@-1{{definition of dllimport static field}} + // expected-note@-2{{attribute is here}} +template<typename T> template<typename U> __declspec(dllimport) const int CTMTR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllimport' attribute}} + // expected-warning@-1{{definition of dllimport static field}} + // expected-note@-2{{attribute is here}} +template<typename T> template<typename U> __declspec(dllimport) constexpr int CTMTR<T>::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllimport' attribute}} + // expected-warning@-1{{definition of dllimport static field}} + // expected-note@-2{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) + + + +//===----------------------------------------------------------------------===// +// Classes +//===----------------------------------------------------------------------===// + +class __declspec(dllimport) ClassDecl; + +class __declspec(dllimport) ClassDef { }; + +template <typename T> class ClassTemplate {}; + +#ifdef MS +// expected-note@+5{{previous attribute is here}} +// expected-note@+4{{previous attribute is here}} +// expected-error@+4{{attribute 'dllexport' cannot be applied to member of 'dllimport' class}} +// expected-error@+4{{attribute 'dllimport' cannot be applied to member of 'dllimport' class}} +#endif +class __declspec(dllimport) ImportClassWithDllMember { + void __declspec(dllexport) foo(); + void __declspec(dllimport) bar(); +}; + +#ifdef MS +// expected-note@+5{{previous attribute is here}} +// expected-note@+4{{previous attribute is here}} +// expected-error@+4{{attribute 'dllimport' cannot be applied to member of 'dllexport' class}} +// expected-error@+4{{attribute 'dllexport' cannot be applied to member of 'dllexport' class}} +#endif +class __declspec(dllexport) ExportClassWithDllMember { + void __declspec(dllimport) foo(); + void __declspec(dllexport) bar(); +}; + +namespace ImportedExplicitSpecialization { +template <typename T> struct S { static int x; }; +template <typename T> int S<T>::x = sizeof(T); +template <> struct __declspec(dllimport) S<int> { static int x; }; // expected-note{{attribute is here}} +int S<int>::x = -1; // expected-error{{definition of dllimport static field not allowed}} +} + +namespace PR19988 { +// Don't error about applying delete to dllimport member function when instantiating. +template <typename> struct __declspec(dllimport) S { + void foo() = delete; +}; +S<int> s; +} + +#ifdef MS +// expected-warning@+3{{'dllimport' attribute ignored}} +#endif +template <typename T> struct PartiallySpecializedClassTemplate {}; +template <typename T> struct __declspec(dllimport) PartiallySpecializedClassTemplate<T*> { void f() {} }; + +template <typename T> struct ExpliciallySpecializedClassTemplate {}; +template <> struct __declspec(dllimport) ExpliciallySpecializedClassTemplate<int> { void f() {} }; + + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template <typename T> class __declspec(dllexport) ExportedClassTemplate {}; + +template <typename T> class __declspec(dllimport) ImportedClassTemplate {}; + +// ClassTemplate<int> gets imported. +class __declspec(dllimport) DerivedFromTemplate : public ClassTemplate<int> {}; + +// ClassTemplate<int> is already imported. +class __declspec(dllimport) DerivedFromTemplate2 : public ClassTemplate<int> {}; + +// ImportedClassTemplate is expliitly imported. +class __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate<int> {}; + +// ExportedClassTemplate is explicitly exported. +class __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate<int> {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate<double>' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template without dll attribute is not supported}} +// expected-note@+3{{attribute is here}} +#endif +class DerivedFromTemplateD : public ClassTemplate<double> {}; +class __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate<bool>' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template with different dll attribute is not supported}} +// expected-note@+3{{attribute is here}} +#endif +class __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> {}; +class __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> {}; + +template <typename T> struct ExplicitlySpecializedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlySpecializedTemplate<int>' was explicitly specialized here}} +#endif +template <> struct ExplicitlySpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate<int> { void func() {} }; +template <typename T> struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate<int> { void func() {} }; + +template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlyInstantiatedTemplate<int>' was instantiated here}} +#endif +template struct ExplicitlyInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to explicitly specialized base class template without dll attribute is not supported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate<int> {}; + +// Base class already specialized with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate<int> {}; + +// Base class already specialized with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate<int> {}; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to already instantiated base class template without dll attribute is not supported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate<int> {}; + +// Base class already instantiated with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate<int> {}; + +// Base class already instantiated with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate<int> {}; diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp index 1b1770a89f850..81c5cb4eac59b 100644 --- a/test/SemaCXX/elaborated-type-specifier.cpp +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -43,3 +43,12 @@ 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; } + +namespace test5 { + struct A { + class __attribute__((visibility("hidden"))) B {}; + + void test(class __attribute__((visibility("hidden"), noreturn)) B b) { // expected-warning {{'noreturn' attribute only applies to functions and methods}} + } + }; +} diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp new file mode 100644 index 0000000000000..e9dc24254f209 --- /dev/null +++ b/test/SemaCXX/enable_if.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +typedef int (*fp)(int); +int surrogate(int); + +struct X { + X() = default; // expected-note{{candidate constructor not viable: requires 0 arguments, but 1 was provided}} + X(const X&) = default; // expected-note{{candidate constructor not viable: no known conversion from 'bool' to 'const X' for 1st argument}} + X(bool b) __attribute__((enable_if(b, "chosen when 'b' is true"))); // expected-note{{candidate disabled: chosen when 'b' is true}} + + void f(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); + void f(int n) __attribute__((enable_if(n == 1, "chosen when 'n' is one"))); // expected-note{{member declaration nearly matches}} expected-note{{candidate disabled: chosen when 'n' is one}} + + static void s(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note2{{candidate disabled: chosen when 'n' is zero}} + + void conflict(int n) __attribute__((enable_if(n+n == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}} + void conflict(int n) __attribute__((enable_if(n*2 == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}} + + operator long() __attribute__((enable_if(true, "chosen on your platform"))); + operator int() __attribute__((enable_if(false, "chosen on other platform"))); + + operator fp() __attribute__((enable_if(false, "never enabled"))) { return surrogate; } // expected-note{{conversion candidate of type 'int (*)(int)'}} // FIXME: the message is not displayed +}; + +void X::f(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))) // expected-note{{member declaration nearly matches}} expected-note{{candidate disabled: chosen when 'n' is zero}} +{ +} + +void X::f(int n) __attribute__((enable_if(n == 2, "chosen when 'n' is two"))) // expected-error{{out-of-line definition of 'f' does not match any declaration in 'X'}} expected-note{{candidate disabled: chosen when 'n' is two}} +{ +} + +X x1(true); +X x2(false); // expected-error{{no matching constructor for initialization of 'X'}} + +__attribute__((deprecated)) constexpr int old() { return 0; } // expected-note2{{'old' has been explicitly marked deprecated here}} +void deprec1(int i) __attribute__((enable_if(old() == 0, "chosen when old() is zero"))); // expected-warning{{'old' is deprecated}} +void deprec2(int i) __attribute__((enable_if(old() == 0, "chosen when old() is zero"))); // expected-warning{{'old' is deprecated}} + +void overloaded(int); +void overloaded(long); + +struct Nothing { }; +template<typename T> void typedep(T t) __attribute__((enable_if(t, ""))); // expected-note{{candidate disabled:}} expected-error{{value of type 'Nothing' is not contextually convertible to 'bool'}} +template<int N> void valuedep() __attribute__((enable_if(N == 1, ""))); + +// FIXME: we skip potential constant expression evaluation on value dependent +// enable-if expressions +int not_constexpr(); +template<int N> void valuedep() __attribute__((enable_if(N == not_constexpr(), ""))); + +template <typename T> void instantiationdep() __attribute__((enable_if(sizeof(sizeof(T)) != 0, ""))); + +void test() { + X x; + x.f(0); + x.f(1); + x.f(2); // no error, suppressed by erroneous out-of-line definition + x.f(3); // expected-error{{no matching member function for call to 'f'}} + + x.s(0); + x.s(1); // expected-error{{no matching member function for call to 's'}} + + X::s(0); + X::s(1); // expected-error{{no matching member function for call to 's'}} + + x.conflict(5); // expected-error{{call to member function 'conflict' is ambiguous}} + + deprec2(0); + + overloaded(x); + + int i = x(1); // expected-error{{no matching function for call to object of type 'X'}} + + Nothing n; + typedep(0); // expected-error{{no matching function for call to 'typedep'}} + typedep(1); + typedep(n); // expected-note{{in instantiation of function template specialization 'typedep<Nothing>' requested here}} +} diff --git a/test/SemaCXX/enum-bitfield.cpp b/test/SemaCXX/enum-bitfield.cpp index 63445ca0583fa..ec849b79a7460 100644 --- a/test/SemaCXX/enum-bitfield.cpp +++ b/test/SemaCXX/enum-bitfield.cpp @@ -16,3 +16,15 @@ struct Y { enum E : int(2); enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}} }; + +namespace pr18587 { +struct A { + enum class B { + C + }; +}; +const int C = 4; +struct D { + A::B : C; +}; +} diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index b4aad18b17c93..1eed2281e9358 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -78,22 +78,22 @@ Complete2 complete2; // All the redeclarations below are done twice on purpose. Tests that the type // of the declaration isn't changed. -enum class Redeclare2; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum class Redeclare2; // expected-note{{previous declaration is here}} expected-note{{previous declaration is here}} enum Redeclare2; // expected-error{{previously declared as scoped}} enum Redeclare2; // expected-error{{previously declared as scoped}} -enum Redeclare3 : int; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum Redeclare3 : int; // expected-note{{previous declaration is here}} expected-note{{previous declaration is here}} enum Redeclare3; // expected-error{{previously declared with fixed underlying type}} enum Redeclare3; // expected-error{{previously declared with fixed underlying type}} enum class Redeclare5; enum class Redeclare5 : int; // ok -enum Redeclare6 : int; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum Redeclare6 : int; // expected-note{{previous declaration is here}} expected-note{{previous declaration is here}} enum Redeclare6 : short; // expected-error{{redeclared with different underlying type}} enum Redeclare6 : short; // expected-error{{redeclared with different underlying type}} -enum class Redeclare7; // expected-note{{previous use is here}} expected-note{{previous use is here}} +enum class Redeclare7; // expected-note{{previous declaration is here}} expected-note{{previous declaration is here}} enum class Redeclare7 : short; // expected-error{{redeclared with different underlying type}} enum class Redeclare7 : short; // expected-error{{redeclared with different underlying type}} @@ -272,6 +272,11 @@ namespace PR16900 { A f(A a) { return -a; } // expected-error {{invalid argument type 'PR16900::A' to unary expression}} } +namespace PR18551 { + enum class A { A }; + bool f() { return !A::A; } // expected-error {{invalid argument type 'PR18551::A' to unary expression}} +} + namespace rdar15124329 { enum class B : bool { F, T }; diff --git a/test/SemaCXX/err_init_conversion_failed.cpp b/test/SemaCXX/err_init_conversion_failed.cpp index 0652e7a9ea6af..e31f215b4528c 100644 --- a/test/SemaCXX/err_init_conversion_failed.cpp +++ b/test/SemaCXX/err_init_conversion_failed.cpp @@ -43,3 +43,19 @@ void test14(const float2 in, const float2 out) { const float4 V = (float4){ in, out }; // expected-error@-1{{cannot initialize a compound literal initializer}} } + +namespace template_test { +class S { +public: + void foo(int); +}; + +template <class P> struct S2 { + void (P::*a)(const int &); +}; + +void test_15() { + S2<S> X = {&S::foo}; + // expected-error-re@-1{{cannot initialize a member subobject of type 'void (template_test::S::*)(const int &){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (template_test::S::*)(int){{( __attribute__\(\(thiscall\)\))?}}': type mismatch at 1st parameter ('const int &' vs 'int')}} +} +} diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp index 1c4d7704511b9..aa28bd85af465 100644 --- a/test/SemaCXX/explicit.cpp +++ b/test/SemaCXX/explicit.cpp @@ -246,3 +246,8 @@ namespace pr8264 { explicit explicit Test(int x); // expected-warning{{duplicate 'explicit' declaration specifier}} }; } + +namespace PR18777 { + struct S { explicit operator bool() const; } s; + int *p = new int(s); // expected-error {{no viable conversion}} +} diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 3a00687f11255..51bb90e8bbf95 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -520,20 +520,19 @@ void expr_cond(bool cond) // 5.16 Conditional operator [expr.cond] // // 2 If either the second or the third operand has type (possibly - // cv-qualified) void, then the lvalue-to-rvalue (4.1), - // array-to-pointer (4.2), and function-to-pointer (4.3) standard - // conversions are performed on the second and third operands, and one - // of the following shall hold: + // cv-qualified) void, one of the following shall hold: // // - The second or the third operand (but not both) is a - // throw-expression (15.1); the result is of the type of the other and - // is an rvalue. + // (possibly parenthesized) throw-expression (15.1); the result + // is of the type and value category of the other. Class classLvalue; ASSERT_RVALUE(cond ? throw 1 : (void)0); ASSERT_RVALUE(cond ? (void)0 : throw 1); - ASSERT_RVALUE(cond ? throw 1 : classLvalue); - ASSERT_RVALUE(cond ? classLvalue : throw 1); + ASSERT_RVALUE(cond ? throw 1 : 0); + ASSERT_RVALUE(cond ? 0 : throw 1); + ASSERT_LVALUE(cond ? throw 1 : classLvalue); + ASSERT_LVALUE(cond ? classLvalue : throw 1); // - Both the second and the third operands have type void; the result // is of type void and is an rvalue. [Note: this includes the case diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp index 2635fb8d176a8..1a50c99c59047 100644 --- a/test/SemaCXX/expressions.cpp +++ b/test/SemaCXX/expressions.cpp @@ -118,3 +118,20 @@ void test3() { (void)s1.foo(); (void)s2.foo(); } + +namespace pr16992 { + typedef int T; + unsigned getsz() { + return (sizeof T()); + } +} + +void test4() { + #define X 0 + #define Y 1 + bool r1 = X || Y; + + #define Y2 2 + bool r2 = X || Y2; // expected-warning {{use of logical '||' with constant operand}} \ + // expected-note {{use '|' for a bitwise operation}} +} diff --git a/test/SemaCXX/flexible-array-test.cpp b/test/SemaCXX/flexible-array-test.cpp index f287711eeb6a5..e58f19a62eca9 100644 --- a/test/SemaCXX/flexible-array-test.cpp +++ b/test/SemaCXX/flexible-array-test.cpp @@ -36,14 +36,20 @@ void foo() } struct S { - virtual void foo(); + virtual void foo(); }; struct X { int blah; - S strings[]; // expected-error {{flexible array member 'strings' of non-POD element type 'S []'}} + S strings[]; }; +S a, b = a; +S f(X &x) { + a = b; + return x.strings[0]; +} + class A { int s; char c[]; @@ -71,3 +77,14 @@ struct VirtStorage : virtual StorageBase { }; } + +struct NonTrivDtor { ~NonTrivDtor(); }; +// FIXME: It's not clear whether we should disallow examples like this. GCC accepts. +struct FlexNonTrivDtor { + int n; + NonTrivDtor ntd[]; // expected-error {{flexible array member 'ntd' of type 'NonTrivDtor []' with non-trivial destruction}} + ~FlexNonTrivDtor() { + for (int i = n; i != 0; --i) + ntd[i-1].~NonTrivDtor(); + } +}; diff --git a/test/SemaCXX/for-range-dereference.cpp b/test/SemaCXX/for-range-dereference.cpp index bf3187da30e2e..7377199024e51 100644 --- a/test/SemaCXX/for-range-dereference.cpp +++ b/test/SemaCXX/for-range-dereference.cpp @@ -11,7 +11,7 @@ struct NoBegin { struct DeletedEnd : public T { Data *begin(); - Data *end() = delete; //expected-note {{function has been explicitly marked deleted here}} + Data *end() = delete; //expected-note {{'end' has been explicitly marked deleted here}} }; struct DeletedADLBegin { }; diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index b3cf9c326421d..2f777fb46df05 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -176,8 +176,9 @@ namespace test4 { // Make sure these don't crash. Better diagnostics would be nice. for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}} - for (x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} - for (y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} + for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} + for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} + for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} } } @@ -209,3 +210,32 @@ namespace test6 { // expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'test6::vector []' is treated as pointer type 'test6::vector *'}} } } + +namespace test7 { + void f() { + int arr[5], b; + for (a : arr) {} // expected-warning {{extension}} + // FIXME: Give a -Wshadow for this by default? + for (b : arr) {} // expected-warning {{extension}} + for (arr : arr) {} // expected-warning {{extension}} + for (c alignas(8) : arr) { // expected-warning {{extension}} + static_assert(alignof(c) == 8, ""); // expected-warning {{extension}} + } + // FIXME: We should reject this, but don't, because we only check the + // attribute before we deduce the 'auto' type. + for (d alignas(1) : arr) {} // expected-warning {{extension}} + for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-warning {{extension}} + } +} + +namespace pr18587 { + class Arg {}; + struct Cont { + int *begin(); + int *end(); + }; + void AddAllArgs(Cont &x) { + for (auto Arg: x) { + } + } +} diff --git a/test/SemaCXX/format-strings.cpp b/test/SemaCXX/format-strings.cpp index 299aa81bb1612..41775708feb71 100644 --- a/test/SemaCXX/format-strings.cpp +++ b/test/SemaCXX/format-strings.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic -fblocks %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks %s #include <stdarg.h> diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp index aed2ab2c7d0c0..03589101e1b85 100644 --- a/test/SemaCXX/friend.cpp +++ b/test/SemaCXX/friend.cpp @@ -288,3 +288,11 @@ namespace test10 { ::test10::f10_d(z); } } + +namespace test11 { + class __attribute__((visibility("hidden"))) B; + + class A { + friend class __attribute__((visibility("hidden"), noreturn)) B; // expected-warning {{'noreturn' attribute only applies to functions and methods}} + }; +} diff --git a/test/SemaCXX/funcdname.cpp b/test/SemaCXX/funcdname.cpp new file mode 100644 index 0000000000000..d63d3f54c3395 --- /dev/null +++ b/test/SemaCXX/funcdname.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++1y -triple i386-pc-win32 -fms-compatibility -fms-extensions -fsyntax-only -verify %s +// expected-no-diagnostics + +int foo() { + static_assert(sizeof(__FUNCDNAME__) == 12, "?foo@@YAHXZ"); + return 0; +} + +// Within templates. +template <typename T> +int baz() { + static_assert(sizeof(__FUNCDNAME__) == 16, "??$baz@H@@YAHXZ"); + + return 0; +} + +struct A { + A() { + static_assert(sizeof(__FUNCDNAME__) == 13, "??0A@@QAE@XZ"); + } + ~A() { + static_assert(sizeof(__FUNCDNAME__) == 13, "??1A@@QAE@XZ"); + } +}; + +int main() { + static_assert(sizeof(__FUNCDNAME__) == 5, "main"); + + baz<int>(); + + return 0; +} diff --git a/test/SemaCXX/functional-cast.cpp b/test/SemaCXX/functional-cast.cpp index f8e0c465875ef..f5ca76c38c065 100644 --- a/test/SemaCXX/functional-cast.cpp +++ b/test/SemaCXX/functional-cast.cpp @@ -305,8 +305,8 @@ void memptrs() (void)structureimfp(psf); typedef void (structure::*structurevmfp)(); - (void)structurevmfp(psi); // expected-error {{functional-style cast from 'const int structure::*' to 'structurevmfp' (aka 'void (structure::*)()') is not allowed}} - (void)structureimp(psf); // expected-error {{functional-style cast from 'void (structure::*)()' to 'structureimp' (aka 'int structure::*') is not allowed}} + (void)structurevmfp(psi); // expected-error-re {{functional-style cast from 'const int structure::*' to 'structurevmfp' (aka 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}') is not allowed}} + (void)structureimp(psf); // expected-error-re {{functional-style cast from 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' to 'structureimp' (aka 'int structure::*') is not allowed}} } // ---------------- misc ------------------ diff --git a/test/SemaCXX/goto.cpp b/test/SemaCXX/goto.cpp index 24bcb7c516738..042ec3cd8035c 100644 --- a/test/SemaCXX/goto.cpp +++ b/test/SemaCXX/goto.cpp @@ -118,7 +118,7 @@ namespace PR10620 { namespace test12 { struct A { A(); A(const A&); ~A(); }; - void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: wierd location + void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: weird location goto lbl; // expected-error {{goto into protected scope}} (void) ^{ (void) a; }; lbl: diff --git a/test/SemaCXX/implicit-member-functions.cpp b/test/SemaCXX/implicit-member-functions.cpp index b5f7fe1016b9d..de679fe14a065 100644 --- a/test/SemaCXX/implicit-member-functions.cpp +++ b/test/SemaCXX/implicit-member-functions.cpp @@ -58,13 +58,13 @@ namespace Recursion { }; struct B; struct A { + // expected-note@-1 {{while substituting deduced template arguments}} typedef B type; template<typename T, typename = typename InvokeCopyConstructor<typename T::type>::type> // expected-note@-1 {{in instantiation of template class}} A(const T &); // expected-note@-1 {{in instantiation of default argument}} - // expected-note@-2 {{while substituting deduced template arguments}} }; struct B { // expected-note {{candidate constructor (the implicit move }} B(); // expected-note {{candidate constructor not viable}} diff --git a/test/SemaCXX/implicit-virtual-member-functions.cpp b/test/SemaCXX/implicit-virtual-member-functions.cpp index cd547f5764593..f88a55c3d5b4b 100644 --- a/test/SemaCXX/implicit-virtual-member-functions.cpp +++ b/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify %s struct A { virtual ~A(); }; @@ -9,8 +10,12 @@ struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} void operator delete (void *, int); // expected-note {{'operator delete' declared here}} }; +#ifdef MSABI +B b; // expected-note {{implicit destructor for 'B' first required here}} +#else void B::f() { // expected-note {{implicit destructor for 'B' first required here}} } +#endif struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} C(); @@ -26,4 +31,3 @@ struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} void f() { new D; // expected-note {{implicit destructor for 'D' first required here}} } - diff --git a/test/SemaCXX/init-priority-attr.cpp b/test/SemaCXX/init-priority-attr.cpp index a91eb60ba96cf..a2e6df26ba1b7 100644 --- a/test/SemaCXX/init-priority-attr.cpp +++ b/test/SemaCXX/init-priority-attr.cpp @@ -25,8 +25,7 @@ Two coo[2] __attribute__((init_priority(3))); // expected-error {{init_priority Two koo[4] __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires an integer constant}} - -Two func() __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} +Two func() __attribute__((init_priority(1001))); // expected-error {{'init_priority' attribute only applies to variables}} int i __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 65f4856dda24c..9a53e4604f763 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -284,6 +284,67 @@ namespace lambdas_in_NSDMIs { } } +// PR18477: don't try to capture 'this' from an NSDMI encountered while parsing +// a lambda. +namespace NSDMIs_in_lambdas { + template<typename T> struct S { int a = 0; int b = a; }; + void f() { []() { S<int> s; }; } + + auto x = []{ struct S { int n, m = n; }; }; + auto y = [&]{ struct S { int n, m = n; }; }; // expected-error {{non-local lambda expression cannot have a capture-default}} + void g() { auto z = [&]{ struct S { int n, m = n; }; }; } +} + +namespace CaptureIncomplete { + struct Incomplete; // expected-note 2{{forward decl}} + void g(const Incomplete &a); + void f(Incomplete &a) { + (void) [a] {}; // expected-error {{incomplete}} + (void) [&a] {}; + + (void) [=] { g(a); }; // expected-error {{incomplete}} + (void) [&] { f(a); }; + } +} + +namespace CaptureAbstract { + struct S { + virtual void f() = 0; // expected-note {{unimplemented}} + int n = 0; + }; + struct T : S { + constexpr T() {} + void f(); + }; + void f() { + constexpr T t = T(); + S &s = const_cast<T&>(t); + // FIXME: Once we properly compute odr-use per DR712, this should be + // accepted (and should not capture 's'). + [=] { return s.n; }; // expected-error {{abstract}} + } +} + +namespace PR18128 { + auto l = [=]{}; // expected-error {{non-local lambda expression cannot have a capture-default}} + + struct S { + int n; + int (*f())[true ? 1 : ([=]{ return n; }(), 0)]; + // expected-error@-1 {{non-local lambda expression cannot have a capture-default}} + // expected-error@-2 {{invalid use of non-static data member 'n'}} + // expected-error@-3 {{a lambda expression may not appear inside of a constant expression}} + int g(int k = ([=]{ return n; }(), 0)); + // expected-error@-1 {{non-local lambda expression cannot have a capture-default}} + // expected-error@-2 {{invalid use of non-static data member 'n'}} + + int a = [=]{ return n; }(); // ok + int b = [=]{ return [=]{ return n; }(); }(); // ok + int c = []{ int k = 0; return [=]{ return k; }(); }(); // ok + int d = []{ return [=]{ return n; }(); }(); // expected-error {{'this' cannot be implicitly captured in this context}} + }; +} + namespace PR18473 { template<typename T> void f() { T t(0); @@ -298,3 +359,7 @@ namespace PR18473 { }; template void f<NoCopy>(); // expected-note {{instantiation}} } + +void PR19249() { + auto x = [&x]{}; // expected-error {{cannot appear in its own init}} +} diff --git a/test/SemaCXX/linkage.cpp b/test/SemaCXX/linkage.cpp index 13d295a5d59b0..8a2013fd52b42 100644 --- a/test/SemaCXX/linkage.cpp +++ b/test/SemaCXX/linkage.cpp @@ -5,6 +5,8 @@ // RUN: %clang_cc1 -Werror -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// CHECK: @_ZZN5test61A3fooEvE3bar = linkonce_odr global i32 0, align 4 + // PR8926 namespace test0 { typedef struct { @@ -103,3 +105,20 @@ namespace test5 { }; } } + +// Test that we don't compute linkage too hastily before we're done +// processing a record decl. rdar://15928125 +namespace test6 { + typedef struct { + int foo() { + // Tested at top of file. + static int bar = 0; + return bar++; + } + } A; + + void test() { + A a; + a.foo(); + } +} diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp index 075f5e70c247d..a7eb15f7c6be6 100644 --- a/test/SemaCXX/linkage2.cpp +++ b/test/SemaCXX/linkage2.cpp @@ -213,3 +213,7 @@ namespace PR16247 { void pr16247_bar(int) {} void pr16247_bar(double) {} } +namespace PR18964 { + unsigned &*foo; //expected-error{{'foo' declared as a pointer to a reference of type}} + extern struct {} *foo; // don't assert +} diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 239aecff815d8..e0955aeb9ce9d 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -193,7 +193,7 @@ namespace PR15045 { }; template <class T> void call_func(T t) { - t->func(); // expected-error-re 2 {{member reference type 'PR15045::bar' is not a pointer$}} \ + t->func(); // expected-error-re 2 {{member reference type 'PR15045::bar' is not a pointer{{$}}}} \ // expected-note {{did you mean to use '.' instead?}} } @@ -207,7 +207,7 @@ namespace PR15045 { // Make sure a fixit isn't given in the case that the '->' isn't actually // the problem (the problem is with the return value of an operator->). - f->func(); // expected-error-re {{member reference type 'PR15045::bar' is not a pointer$}} + f->func(); // expected-error-re {{member reference type 'PR15045::bar' is not a pointer{{$}}}} call_func(e); // expected-note {{in instantiation of function template specialization 'PR15045::call_func<PR15045::bar>' requested here}} diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 6e4fd5df5a08a..d8a00b3b1e24d 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -100,3 +100,13 @@ namespace rdar14084171 { }; void f(Sprite& x) { x = x; } } + +namespace PR18560 { + struct X { int m; }; + + template<typename T = X, + typename U = decltype(T::m)> + int f(); + + struct Y { int b = f(); }; +} diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp index aee8e2eca7742..e7c4ae9409e04 100644 --- a/test/SemaCXX/member-pointer-ms.cpp +++ b/test/SemaCXX/member-pointer-ms.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s -// RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify -DVMB %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMB %s +// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify -DVMV -fms-memptr-rep=virtual %s // // This file should also give no diagnostics when run through cl.exe from MSVS // 2012, which supports C++11 and static_assert. It should pass for both 64-bit @@ -18,22 +19,73 @@ struct Foo { int f; }; +#ifdef VMB enum { + kSingleDataAlign = 1 * sizeof(int), + kSingleFunctionAlign = 1 * sizeof(void *), + kMultipleDataAlign = 1 * sizeof(int), + // Everything with more than 1 field is 8 byte aligned, except virtual data + // member pointers on x64 (ugh). + kMultipleFunctionAlign = 8, +#ifdef _M_X64 + kVirtualDataAlign = 4, +#else + kVirtualDataAlign = 8, +#endif + kVirtualFunctionAlign = 8, + kUnspecifiedDataAlign = 8, + kUnspecifiedFunctionAlign = 8, + kSingleDataSize = 1 * sizeof(int), kSingleFunctionSize = 1 * sizeof(void *), kMultipleDataSize = 1 * sizeof(int), kMultipleFunctionSize = 2 * sizeof(void *), kVirtualDataSize = 2 * sizeof(int), kVirtualFunctionSize = 2 * sizeof(int) + 1 * sizeof(void *), - // Unspecified is weird, it's 1 more slot than virtual. - kUnspecifiedDataSize = kVirtualDataSize + 1 * sizeof(int), - kUnspecifiedFunctionSize = kVirtualFunctionSize + 1 * sizeof(void *), + kUnspecifiedDataSize = 3 * sizeof(int), + kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *), +}; +#elif VMV +enum { + // Everything with more than 1 field is 8 byte aligned, except virtual data + // member pointers on x64 (ugh). +#ifdef _M_X64 + kVirtualDataAlign = 4, +#else + kVirtualDataAlign = 8, +#endif + kMultipleDataAlign = kVirtualDataAlign, + kSingleDataAlign = kVirtualDataAlign, + + kUnspecifiedFunctionAlign = 8, + kVirtualFunctionAlign = kUnspecifiedFunctionAlign, + kMultipleFunctionAlign = kUnspecifiedFunctionAlign, + kSingleFunctionAlign = kUnspecifiedFunctionAlign, + + kUnspecifiedDataSize = 3 * sizeof(int), + kVirtualDataSize = kUnspecifiedDataSize, + kMultipleDataSize = kUnspecifiedDataSize, + kSingleDataSize = kUnspecifiedDataSize, + + kUnspecifiedFunctionSize = 2 * sizeof(int) + 2 * sizeof(void *), + kVirtualFunctionSize = kUnspecifiedFunctionSize, + kMultipleFunctionSize = kUnspecifiedFunctionSize, + kSingleFunctionSize = kUnspecifiedFunctionSize, }; +#else +#error "test doesn't yet support this mode!" +#endif // incomplete types +#ifdef VMB class __single_inheritance IncSingle; class __multiple_inheritance IncMultiple; class __virtual_inheritance IncVirtual; +#else +class IncSingle; +class IncMultiple; +class IncVirtual; +#endif static_assert(sizeof(int IncSingle::*) == kSingleDataSize, ""); static_assert(sizeof(int IncMultiple::*) == kMultipleDataSize, ""); static_assert(sizeof(int IncVirtual::*) == kVirtualDataSize, ""); @@ -41,6 +93,13 @@ static_assert(sizeof(void (IncSingle::*)()) == kSingleFunctionSize, ""); static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, ""); static_assert(sizeof(void (IncVirtual::*)()) == kVirtualFunctionSize, ""); +static_assert(__alignof(int IncSingle::*) == kSingleDataAlign, ""); +static_assert(__alignof(int IncMultiple::*) == kMultipleDataAlign, ""); +static_assert(__alignof(int IncVirtual::*) == kVirtualDataAlign, ""); +static_assert(__alignof(void (IncSingle::*)()) == kSingleFunctionAlign, ""); +static_assert(__alignof(void (IncMultiple::*)()) == kMultipleFunctionAlign, ""); +static_assert(__alignof(void (IncVirtual::*)()) == kVirtualFunctionAlign, ""); + // An incomplete type with an unspecified inheritance model seems to take one // more slot than virtual. It's not clear what it's used for yet. class IncUnspecified; @@ -62,9 +121,15 @@ static_assert(sizeof(void (Virtual::*)()) == kVirtualFunctionSize, ""); // Test both declared and defined templates. template <typename T> class X; +#ifdef VMB template <> class __single_inheritance X<IncSingle>; template <> class __multiple_inheritance X<IncMultiple>; template <> class __virtual_inheritance X<IncVirtual>; +#else +template <> class X<IncSingle>; +template <> class X<IncMultiple>; +template <> class X<IncVirtual>; +#endif // Don't declare X<IncUnspecified>. static_assert(sizeof(int X<IncSingle>::*) == kSingleDataSize, ""); static_assert(sizeof(int X<IncMultiple>::*) == kMultipleDataSize, ""); @@ -117,9 +182,7 @@ struct ForwardDecl2 : B { static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, ""); static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, ""); -// FIXME: Clang fails this assert because it locks in the inheritance model at -// the point of the typedef instead of the first usage, while MSVC does not. -//static_assert(sizeof(MemPtr2) == kSingleDataSize, ""); +static_assert(sizeof(MemPtr2) == kSingleDataSize, ""); struct MemPtrInBody { typedef int MemPtrInBody::*MemPtr; @@ -164,5 +227,48 @@ struct MemPtrInTemplate { void (T::*func_ptr)(); }; +#ifdef VMB int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x); // expected-error@-1 {{cannot reinterpret_cast from member pointer type}} +#endif + +namespace ErrorTest { +template <typename T, typename U> struct __single_inheritance A; + // expected-warning@-1 {{inheritance model ignored on primary template}} +template <typename T> struct __multiple_inheritance A<T, T>; + // expected-warning@-1 {{inheritance model ignored on partial specialization}} +template <> struct __single_inheritance A<int, float>; + +struct B {}; // expected-note {{B defined here}} +struct __multiple_inheritance B; // expected-error{{inheritance model does not match definition}} + +struct __multiple_inheritance C {}; // expected-error{{inheritance model does not match definition}} + // expected-note@-1 {{C defined here}} + +struct __virtual_inheritance D; +struct D : virtual B {}; +} +#ifdef VMB +#pragma pointers_to_members(full_generality, multiple_inheritance) +struct TrulySingleInheritance; +static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, ""); +#pragma pointers_to_members(best_case) +// This definition shouldn't conflict with the increased generality that the +// multiple_inheritance model gave to TrulySingleInheritance. +struct TrulySingleInheritance {}; + +// Even if a definition proceeds the first mention of a pointer to member, we +// still give the record the fully general representation. +#pragma pointers_to_members(full_generality, virtual_inheritance) +struct SingleInheritanceAsVirtualAfterPragma {}; +static_assert(sizeof(int SingleInheritanceAsVirtualAfterPragma::*) == 12, ""); + +#pragma pointers_to_members(best_case) + +// The above holds even if the pragma comes after the definition. +struct SingleInheritanceAsVirtualBeforePragma {}; +#pragma pointers_to_members(virtual_inheritance) +static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, ""); + +#pragma pointers_to_members(single) // expected-error{{unexpected 'single'}} +#endif diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index 4e8b4a813ba73..b8631bcf3efc9 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -7,12 +7,13 @@ struct D : A {}; struct E : A {}; struct F : D, E {}; struct G : virtual D {}; +class H : A {}; // expected-note 2{{implicitly declared private here}} int A::*pdi1; int (::A::*pdi2); int (A::*pfi)(int); -int B::*pbi; // expected-error {{expected a class or namespace}} +int B::*pbi; // expected-error {{'B' is not a class, namespace, or scoped enumeration}} int C::*pci; // expected-error {{'pci' does not point into a class}} void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}} int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}} @@ -115,8 +116,11 @@ void h() { (void)(d.*pai); (void)(pd->*pai); F f, *ptrf = &f; - (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'F'}} - (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'F *'}} + (void)(f.*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}} + (void)(ptrf->*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}} + H h, *ptrh = &h; + (void)(h.*pai); // expected-error {{cannot cast 'H' to its private base class 'A'}} + (void)(ptrh->*pai); // expected-error {{cannot cast 'H' to its private base class 'A'}} (void)(hm.*i); // expected-error {{pointer-to-member}} (void)(phm->*i); // expected-error {{pointer-to-member}} diff --git a/test/SemaCXX/microsoft-cxx0x.cpp b/test/SemaCXX/microsoft-cxx0x.cpp index 79bd7c39e5a54..58ab940f583ea 100644 --- a/test/SemaCXX/microsoft-cxx0x.cpp +++ b/test/SemaCXX/microsoft-cxx0x.cpp @@ -6,7 +6,7 @@ struct A { unsigned int a; }; int b = 3; -A var = { b }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} +A var = { b }; // expected-warning {{ cannot be narrowed }} expected-note {{insert an explicit cast to silence this issue}} namespace PR13433 { diff --git a/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp b/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp new file mode 100644 index 0000000000000..5a399aa7eac22 --- /dev/null +++ b/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -std=c++11 -verify %s + +struct S { + virtual ~S() = delete; // expected-note {{'~S' has been explicitly marked deleted here}} + void operator delete(void*, int); + void operator delete(void*, double); +} s; // expected-error {{attempt to use a deleted function}} + +struct T { // expected-note{{virtual destructor requires an unambiguous, accessible 'operator delete'}} + virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} + void operator delete(void*, int); + void operator delete(void*, double); +} t; // expected-error {{attempt to use a deleted function}} diff --git a/test/SemaCXX/microsoft-dtor-lookup.cpp b/test/SemaCXX/microsoft-dtor-lookup.cpp index d264bab09bf74..412749f707ee4 100644 --- a/test/SemaCXX/microsoft-dtor-lookup.cpp +++ b/test/SemaCXX/microsoft-dtor-lookup.cpp @@ -1,12 +1,11 @@ -// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi itanium -fsyntax-only %s -// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -verify -DMSVC_ABI %s +// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -std=c++11 -triple %itanium_abi_triple -fsyntax-only %s +// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -std=c++11 -triple %ms_abi_triple -verify %s namespace Test1 { // Should be accepted under the Itanium ABI (first RUN line) but rejected // under the Microsoft ABI (second RUN line), as Microsoft ABI requires -// operator delete() lookups to be done at all virtual destructor declaration -// points. +// operator delete() lookups to be done when vtables are marked used. struct A { void operator delete(void *); // expected-note {{member found by ambiguous name lookup}} @@ -24,6 +23,10 @@ struct VC : A, B { virtual ~VC(); // expected-error {{member 'operator delete' found in multiple base classes of different types}} }; +void f(VC vc) { + // This marks VC's vtable used. +} + } namespace Test2 { @@ -32,14 +35,13 @@ namespace Test2 { // requires a dtor for B, but we can't implicitly define it because ~A is // private. bar should be able to call A's private dtor without error, even // though MSVC rejects bar. - class A { private: - ~A(); // expected-note 2{{declared private here}} + ~A(); int a; }; -struct B : public A { // expected-error {{base class 'Test2::A' has private destructor}} +struct B : public A { // expected-note {{destructor of 'B' is implicitly deleted because base class 'Test2::A' has an inaccessible destructor}} int b; }; @@ -53,8 +55,8 @@ struct D { C o; }; -void foo(B b) { } // expected-note {{implicit destructor for 'Test2::B' first required here}} -void bar(A a) { } // expected-error {{variable of type 'Test2::A' has private destructor}} +void foo(B b) { } // expected-error {{attempt to use a deleted function}} +void bar(A a) { } // no error; MSVC rejects this, but we skip the direct access check. void baz(D d) { } // no error } @@ -64,13 +66,13 @@ namespace Test3 { class A { A(); - ~A(); // expected-note 2{{implicitly declared private here}} + ~A(); // expected-note {{implicitly declared private here}} friend void bar(A); int a; }; void bar(A a) { } -void baz(A a) { } // expected-error {{variable of type 'Test3::A' has private destructor}} +void baz(A a) { } // no error; MSVC rejects this, but the standard allows it. // MSVC accepts foo() but we reject it for consistency with Itanium. MSVC also // rejects this if A has a copy ctor or if we call A's ctor. @@ -85,3 +87,45 @@ namespace Test4 { class A; void foo(A a); } + +#ifdef MSVC_ABI +namespace Test5 { +// Do the operator delete access control check from the context of the dtor. +class A { + protected: + void operator delete(void *); +}; +class B : public A { + virtual ~B(); +}; +B *test() { + // Previously, marking the vtable used here would do the operator delete + // lookup from this context, which doesn't have access. + return new B; +} +} +#endif + +namespace Test6 { +class A { +protected: + void operator delete(void *); +}; +class B : public A { + virtual ~B(); +public: + virtual void m_fn1(); +}; +void fn1(B *b) { b->m_fn1(); } +} + +namespace Test7 { +class A { +protected: + void operator delete(void *); +}; +struct B : public A { + virtual ~B(); +}; +void fn1(B b) {} +} diff --git a/test/SemaCXX/microsoft-new-delete.cpp b/test/SemaCXX/microsoft-new-delete.cpp index e0d25dcd86f78..6c9be228935ee 100644 --- a/test/SemaCXX/microsoft-new-delete.cpp +++ b/test/SemaCXX/microsoft-new-delete.cpp @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify -std=c++11 %s #include <stddef.h> @@ -10,3 +9,26 @@ void f() { // Expect no error in MSVC compatibility mode int *p = new(arbitrary) int[4]; } + +class noncopyable { noncopyable(const noncopyable&); } extern nc; // expected-note {{here}} +void *operator new[](size_t, noncopyable); +void *operator new(size_t, const noncopyable&); +void *q = new (nc) int[4]; // expected-error {{calling a private constructor}} + +struct bitfield { int n : 3; } bf; // expected-note {{here}} +void *operator new[](size_t, int &); +void *operator new(size_t, const int &); +void *r = new (bf.n) int[4]; // expected-error {{non-const reference cannot bind to bit-field}} + +struct base {}; +struct derived : private base {} der; // expected-note {{here}} +void *operator new[](size_t, base &); +void *operator new(size_t, derived &); +void *s = new (der) int[4]; // expected-error {{private}} + +struct explicit_ctor { explicit explicit_ctor(int); }; +struct explicit_ctor_tag {} ect; +void *operator new[](size_t, explicit_ctor_tag, explicit_ctor); +void *operator new(size_t, explicit_ctor_tag, int); +void *t = new (ect, 0) int[4]; +void *u = new (ect, {0}) int[4]; diff --git a/test/SemaCXX/microsoft-varargs-diagnostics.cpp b/test/SemaCXX/microsoft-varargs-diagnostics.cpp new file mode 100644 index 0000000000000..0b76fdd92dabd --- /dev/null +++ b/test/SemaCXX/microsoft-varargs-diagnostics.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -fsyntax-only %s -verify + +extern "C" { +typedef char * va_list; +} + +void test_no_arguments(int i, ...) { + __va_start(); // expected-error{{too few arguments to function call, expected at least 3, have 0}} +} + +void test_one_argument(int i, ...) { + va_list ap; + __va_start(&ap); // expected-error{{too few arguments to function call, expected at least 3, have 1}} +} + +void test_two_arguments(int i, ...) { + va_list ap; + __va_start(&ap, &i); // expected-error{{too few arguments to function call, expected at least 3, have 2}} +} + +void test_non_last_argument(int i, int j, ...) { + va_list ap; + __va_start(&ap, &i, 4); + // expected-error@-1{{passing 'int *' to parameter of incompatible type 'const char *': type mismatch at 2nd parameter ('int *' vs 'const char *')}} + // expected-error@-2{{passing 'int' to parameter of incompatible type 'unsigned int': type mismatch at 3rd parameter ('int' vs 'unsigned int')}} +} + +void test_stack_allocated(int i, ...) { + va_list ap; + int j; + __va_start(&ap, &j, 4); + // expected-error@-1{{passing 'int *' to parameter of incompatible type 'const char *': type mismatch at 2nd parameter ('int *' vs 'const char *')}} + // expected-error@-2{{passing 'int' to parameter of incompatible type 'unsigned int': type mismatch at 3rd parameter ('int' vs 'unsigned int')}} +} + +void test_non_pointer_addressof(int i, ...) { + va_list ap; + __va_start(&ap, 1, 4); + // expected-error@-1{{passing 'int' to parameter of incompatible type 'const char *': type mismatch at 2nd parameter ('int' vs 'const char *')}} + // expected-error@-2{{passing 'int' to parameter of incompatible type 'unsigned int': type mismatch at 3rd parameter ('int' vs 'unsigned int')}} +} + diff --git a/test/SemaCXX/microsoft-varargs.cpp b/test/SemaCXX/microsoft-varargs.cpp new file mode 100644 index 0000000000000..35f31a97c4f16 --- /dev/null +++ b/test/SemaCXX/microsoft-varargs.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -fsyntax-only %s -verify +// expected-no-diagnostics + +extern "C" { +typedef char * va_list; +void __va_start(va_list *, ...); +} + +int test___va_start(int i, ...) { + va_list ap; + __va_start(&ap, ( &reinterpret_cast<const char &>(i) ), + ( (sizeof(i) + 4 - 1) & ~(4 - 1) ), + ( &reinterpret_cast<const char &>(i) )); + return (*(int *)((ap += ( (sizeof(int) + 4 - 1) & ~(4 - 1) ) + ( ((va_list)0 - (ap)) & (__alignof(int) - 1) )) - ( (sizeof(int) + 4 - 1) & ~(4 - 1) ))); +} + +int builtin(int i, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, i); + return __builtin_va_arg(ap, int); +} + diff --git a/test/SemaCXX/missing-members.cpp b/test/SemaCXX/missing-members.cpp index 619bc61f25011..96bed074db857 100644 --- a/test/SemaCXX/missing-members.cpp +++ b/test/SemaCXX/missing-members.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s namespace A { namespace B { - class C { }; // expected-note 2 {{'A::B::C' declared here}} + class C { }; // expected-note {{'A::B::C' declared here}} struct S { }; union U { }; } @@ -18,13 +18,12 @@ namespace B { } void g() { - A::B::D::E; // expected-error {{no member named 'D' in namespace 'A::B'}} + A::B::D::E; // expected-error-re {{no member named 'D' in namespace 'A::B'{{$}}}} // FIXME: The typo corrections below should be suppressed since A::B::C // doesn't have a member named D. B::B::C::D; // expected-error {{no member named 'C' in 'B::B'; did you mean 'A::B::C'?}} \ - // expected-error {{no member named 'D' in 'A::B::C'}} - ::C::D; // expected-error {{no member named 'C' in the global namespace; did you mean 'A::B::C'?}}\ - // expected-error {{no member named 'D' in 'A::B::C'}} + // expected-error-re {{no member named 'D' in 'A::B::C'{{$}}}} + ::C::D; // expected-error-re {{no member named 'C' in the global namespace{{$}}}} } int A::B::i = 10; // expected-error {{no member named 'i' in namespace 'A::B'}} diff --git a/test/SemaCXX/ms-friend-lookup.cpp b/test/SemaCXX/ms-friend-lookup.cpp new file mode 100644 index 0000000000000..c63160f5b9f9c --- /dev/null +++ b/test/SemaCXX/ms-friend-lookup.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -Wmicrosoft -fms-compatibility -verify +// RUN: not %clang_cc1 %s -triple i686-pc-win32 -std=c++11 -Wmicrosoft -fms-compatibility -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s + +struct X; +namespace name_at_tu_scope { +struct Y { + friend struct X; // expected-warning-re {{unqualified friend declaration {{.*}} is a Microsoft extension}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"::" +}; +} + +namespace enclosing_friend_decl { +struct B; +namespace ns { +struct A { + friend struct B; // expected-warning-re {{unqualified friend declaration {{.*}} is a Microsoft extension}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"enclosing_friend_decl::" +protected: + A(); +}; +} +struct B { + static void f() { ns::A x; } +}; +} + +namespace enclosing_friend_qualified { +struct B; +namespace ns { +struct A { + friend struct enclosing_friend_qualified::B; // Adding name specifiers fixes it. +protected: + A(); +}; +} +struct B { + static void f() { ns::A x; } +}; +} + +namespace enclosing_friend_no_tag { +struct B; +namespace ns { +struct A { + friend B; // Removing the tag decl fixes it. +protected: + A(); +}; +} +struct B { + static void f() { ns::A x; } +}; +} + +namespace enclosing_friend_func { +void f(); +namespace ns { +struct A { + // Amusingly, in MSVC, this declares ns::f(), and doesn't find the outer f(). + friend void f(); +protected: + A(); // expected-note {{declared protected here}} +}; +} +void f() { ns::A x; } // expected-error {{calling a protected constructor of class 'enclosing_friend_func::ns::A'}} +} + +namespace test_nns_fixit_hint { +namespace name1 { +namespace name2 { +struct X; +struct name2; +namespace name3 { +struct Y { + friend struct X; // expected-warning-re {{unqualified friend declaration {{.*}} is a Microsoft extension}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"name1::name2::" +}; +} +} +} +} + +// A friend declaration injects a forward declaration into the nearest enclosing +// non-member scope. +namespace friend_as_a_forward_decl { + +class A { + class Nested { + friend class B; + B *b; + }; + B *b; +}; +B *global_b; + +void f() { + class Local { + friend class Z; + Z *b; + }; + Z *b; +} + +} diff --git a/test/SemaCXX/ms-interface.cpp b/test/SemaCXX/ms-interface.cpp index 3625f7027aa47..e7386ce5b8e7b 100644 --- a/test/SemaCXX/ms-interface.cpp +++ b/test/SemaCXX/ms-interface.cpp @@ -10,7 +10,7 @@ __interface I1 { bool operator!(); // expected-error@+1 {{operator 'operator int' is not permitted within an interface type}} operator int(); - // expected-error@+1 {{nested class I1::<anonymous> is not permitted within an interface type}} + // expected-error@+1 {{nested class I1::(anonymous) is not permitted within an interface type}} struct { int a; }; void fn2() { struct A { }; // should be ignored: not a nested class diff --git a/test/SemaCXX/ms_integer_suffix.cpp b/test/SemaCXX/ms_integer_suffix.cpp new file mode 100644 index 0000000000000..6b4594dd5b55d --- /dev/null +++ b/test/SemaCXX/ms_integer_suffix.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fms-extensions -verify %s +// expected-no-diagnostics + +#ifdef __SIZEOF_INT8__ +static_assert(sizeof(0i8) == __SIZEOF_INT8__, ""); +#endif +#ifdef __SIZEOF_INT16__ +static_assert(sizeof(0i16) == __SIZEOF_INT16__, ""); +#endif +#ifdef __SIZEOF_INT32__ +static_assert(sizeof(0i32) == __SIZEOF_INT32__, ""); +#endif +#ifdef __SIZEOF_INT64__ +static_assert(sizeof(0i64) == __SIZEOF_INT64__, ""); +#endif +#ifdef __SIZEOF_INT128__ +static_assert(sizeof(0i128) == __SIZEOF_INT128__, ""); +#endif diff --git a/test/SemaCXX/ms_struct.cpp b/test/SemaCXX/ms_struct.cpp index 37fa9a7c687ca..2832b5620f3b6 100644 --- a/test/SemaCXX/ms_struct.cpp +++ b/test/SemaCXX/ms_struct.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin9 -std=c++11 %s -// expected-no-diagnostics +// RUN: %clang_cc1 -fsyntax-only -Wno-error=incompatible-ms-struct -verify -triple i686-apple-darwin9 -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -Wno-error=incompatible-ms-struct -verify -triple armv7-apple-darwin9 -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -DTEST_FOR_ERROR -verify -triple armv7-apple-darwin9 -std=c++11 %s #pragma ms_struct on @@ -9,10 +10,29 @@ struct A { }; struct B : public A { +#ifdef TEST_FOR_ERROR + // expected-error@-2 {{ms_struct may not produce MSVC-compatible layouts for classes with base classes or virtual functions}} +#else + // expected-warning@-4 {{ms_struct may not produce MSVC-compatible layouts for classes with base classes or virtual functions}} +#endif unsigned long c:16; int d; B(); }; static_assert(__builtin_offsetof(B, d) == 12, - "We can't allocate the bitfield into the padding under ms_struct");
\ No newline at end of file + "We can't allocate the bitfield into the padding under ms_struct"); + +// rdar://16178895 +struct C { +#ifdef TEST_FOR_ERROR + // expected-error@-2 {{ms_struct may not produce MSVC-compatible layouts for classes with base classes or virtual functions}} +#else + // expected-warning@-4 {{ms_struct may not produce MSVC-compatible layouts for classes with base classes or virtual functions}} +#endif + virtual void foo(); + long long n; +}; + +static_assert(__builtin_offsetof(C, n) == 8, + "long long field in ms_struct should be 8-byte aligned"); diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index df4f1b269d70a..bdeb00d357347 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -8,13 +8,12 @@ namespace A { static int Ag1(); static int Ag2(); }; - int ax; + int ax; // expected-note {{'ax' declared here}} void Af(); } A:: ; // expected-error {{expected unqualified-id}} -// FIXME: there is a member 'ax'; it's just not a class. -::A::ax::undef ex3; // expected-error {{no member named 'ax'}} +::A::ax::undef ex3; // expected-error {{'ax' is not a class, namespace, or scoped enumeration}} A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} int A::C::Ag1() { return 0; } @@ -85,10 +84,13 @@ struct A2::CC::NC { void f3() { N::x = 0; // expected-error {{use of undeclared identifier 'N'}} - int N; - N::x = 0; // expected-error {{expected a class or namespace}} + // FIXME: Consider including the kind of entity that 'N' is ("variable 'N' + // declared here", "template 'X' declared here", etc) to help explain what it + // is if it's 'not a class, namespace, or scoped enumeration'. + int N; // expected-note {{'N' declared here}} + N::x = 0; // expected-error {{'N' is not a class, namespace, or scoped enumeration}} { int A; A::ax = 0; } - { typedef int A; A::ax = 0; } // expected-error{{expected a class or namespace}} + { typedef int A; A::ax = 0; } // expected-error{{'A' (aka 'int') is not a class, namespace, or scoped enumeration}} { typedef A::C A; A::ax = 0; } // expected-error {{no member named 'ax'}} { typedef A::C A; A::cx = 0; } } @@ -114,7 +116,7 @@ namespace E { }; void f() { - return E::X; // expected-error{{expected a class or namespace}} + return E::X; // expected-error{{'E::Nested::E' is not a class, namespace, or scoped enumeration}} } } } @@ -143,7 +145,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-re{{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'}} @@ -160,7 +162,7 @@ namespace N { void f(); // FIXME: if we move this to a separate definition of N, things break! } -void ::global_func2(int) { } // expected-error{{extra qualification on member 'global_func2'}} +void ::global_func2(int) { } // expected-warning{{extra qualification on member 'global_func2'}} void N::f() { } // okay @@ -308,4 +310,103 @@ namespace N { } namespace TypedefNamespace { typedef int F; }; -TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error {{expected a class or namespace}} +TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error {{'F' (aka 'int') is not a class, namespace, or scoped enumeration}} + +namespace PR18587 { + +struct C1 { + int a, b, c; + typedef int C2; + struct B1 { + struct B2 { + int a, b, c; + }; + }; +}; +struct C2 { static const unsigned N1 = 1; }; +struct B1 { + enum E1 { B2 = 2 }; + static const int B3 = 3; +}; +const int N1 = 2; + +// Function declarators +struct S1a { int f(C1::C2); }; +struct S1b { int f(C1:C2); }; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} + +struct S2a { + C1::C2 f(C1::C2); +}; +struct S2c { + C1::C2 f(C1:C2); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; + +struct S3a { + int f(C1::C2), C2 : N1; + int g : B1::B2; +}; +struct S3b { + int g : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; + +// Inside square brackets +struct S4a { + int f[C2::N1]; +}; +struct S4b { + int f[C2:N1]; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; + +struct S5a { + int f(int xx[B1::B3 ? C2::N1 : B1::B2]); +}; +struct S5b { + int f(int xx[B1::B3 ? C2::N1 : B1:B2]); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; +struct S5c { + int f(int xx[B1:B3 ? C2::N1 : B1::B2]); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; + +// Bit fields +struct S6a { + C1::C2 m1 : B1::B2; +}; +struct S6c { + C1::C2 m1 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; +struct S6d { + int C2:N1; +}; +struct S6e { + static const int N = 3; + B1::E1 : N; +}; +struct S6g { + C1::C2 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} + B1::E1 : B1:B2; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; + +// Template parameters +template <int N> struct T1 { + int a,b,c; + static const unsigned N1 = N; + typedef unsigned C1; +}; +T1<C2::N1> var_1a; +T1<C2:N1> var_1b; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +template<int N> int F() {} +int (*X1)() = (B1::B2 ? F<1> : F<2>); +int (*X2)() = (B1:B2 ? F<1> : F<2>); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} + +// Bit fields + templates +struct S7a { + T1<B1::B2>::C1 m1 : T1<B1::B2>::N1; +}; +struct S7b { + T1<B1:B2>::C1 m1 : T1<B1::B2>::N1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; +struct S7c { + T1<B1::B2>::C1 m1 : T1<B1:B2>::N1; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} +}; + +} diff --git a/test/SemaCXX/new-delete-cxx0x.cpp b/test/SemaCXX/new-delete-cxx0x.cpp index c404faba2a251..899cb4cda87a2 100644 --- a/test/SemaCXX/new-delete-cxx0x.cpp +++ b/test/SemaCXX/new-delete-cxx0x.cpp @@ -2,8 +2,8 @@ void ugly_news(int *ip) { // These are ill-formed according to one reading of C++98, and at the least - // have undefined behavior. But they're well-formed, and defined to throw - // std::bad_array_new_length, in C++11. + // have undefined behavior. + // FIXME: They're ill-formed in C++11. (void)new int[-1]; // expected-warning {{array size is negative}} (void)new int[2000000000]; // expected-warning {{array is too large}} } @@ -22,5 +22,12 @@ struct T { // expected-note 2 {{not viable}} void fn() { (void) new int[2] {1, 2}; (void) new S[2] {1, 2}; - (void) new T[2] {1, 2}; // expected-error {{no matching constructor}} + // C++11 [expr.new]p19: + // If the new-expression creates an object or an array of objects of class + // type, access and ambiguity control are done for the allocation function, + // the deallocation function (12.5), and the constructor (12.1). + // + // Note that this happens even if the array bound is constant and the + // initializer initializes every array element. + (void) new T[2] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 2}} } diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 7facd10ca5fc8..cb43458d45786 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu -Wno-new-returns-null #include <stddef.h> @@ -517,3 +517,10 @@ class DeletingPlaceholder { return 0; } }; + +namespace PR18544 { + inline void *operator new(size_t); // expected-error {{'operator new' cannot be declared inside a namespace}} +} + +// PR19968 +inline void* operator new(); // expected-error {{'operator new' must have at least one parameter}} diff --git a/test/SemaCXX/new-null.cpp b/test/SemaCXX/new-null.cpp new file mode 100644 index 0000000000000..b2be0c5b382f2 --- /dev/null +++ b/test/SemaCXX/new-null.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +typedef __SIZE_TYPE__ size_t; + +#if __cplusplus >= 201103L +struct S1 { + void *operator new(size_t n) { + return nullptr; // expected-warning {{'operator new' should not return a null pointer unless it is declared 'throw()' or 'noexcept'}} + } + void *operator new[](size_t n) noexcept { + return __null; + } +}; +#endif + +struct S2 { + static size_t x; + void *operator new(size_t n) throw() { + return 0; + } + void *operator new[](size_t n) { + return (void*)0; +#if __cplusplus >= 201103L + // expected-warning@-2 {{'operator new[]' should not return a null pointer unless it is declared 'throw()' or 'noexcept'}} +#else + // expected-warning-re@-4 {{'operator new[]' should not return a null pointer unless it is declared 'throw()'{{$}}}} +#endif + } +}; + +struct S3 { + void *operator new(size_t n) { + return 1-1; +#if __cplusplus >= 201103L + // expected-error@-2 {{cannot initialize return object of type 'void *' with an rvalue of type 'int'}} +#else + // expected-warning@-4 {{expression which evaluates to zero treated as a null pointer constant of type 'void *'}} + // expected-warning@-5 {{'operator new' should not return a null pointer unless it is declared 'throw()'}} +#endif + } + void *operator new[](size_t n) { + return (void*)(1-1); // expected-warning {{'operator new[]' should not return a null pointer unless it is declared 'throw()'}} + } +}; + +#if __cplusplus >= 201103L +template<bool B> struct S4 { + void *operator new(size_t n) noexcept(B) { + return 0; // expected-warning {{'operator new' should not return a null pointer}} + } +}; +template struct S4<true>; +template struct S4<false>; // expected-note {{in instantiation of}} +#endif + +template<typename ...T> struct S5 { // expected-warning 0-1{{extension}} + void *operator new(size_t n) throw(T...) { + return 0; // expected-warning {{'operator new' should not return a null pointer}} + } +}; +template struct S5<>; +template struct S5<int>; // expected-note {{in instantiation of}} diff --git a/test/SemaCXX/nonnull.cpp b/test/SemaCXX/nonnull.cpp new file mode 100644 index 0000000000000..9ff6d115bd16b --- /dev/null +++ b/test/SemaCXX/nonnull.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<int I> +struct TS { + __attribute__((returns_nonnull)) + void *value_dependent(void) { + return I; // no-warning + } + + __attribute__((returns_nonnull)) + void *value_independent(void) { + return 0; // expected-warning {{null returned from function that requires a non-null return value}} + } +}; + diff --git a/test/SemaCXX/ns_returns_retained_block_return.cpp b/test/SemaCXX/ns_returns_retained_block_return.cpp new file mode 100644 index 0000000000000..9d04536e0f1b9 --- /dev/null +++ b/test/SemaCXX/ns_returns_retained_block_return.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fblocks -fsyntax-only -verify %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fsyntax-only -verify %s +// expected-no-diagnostics +// rdar://17259812 + +typedef void (^BT) (); + +class S { + BT br() __attribute__((ns_returns_retained)) { + return ^{}; + } + BT br1() __attribute__((ns_returns_retained)); +}; + +BT S::br1() { + return ^{}; +} diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp index a919213fb2085..3b42ab44feb9e 100644 --- a/test/SemaCXX/null_in_arithmetic_ops.cpp +++ b/test/SemaCXX/null_in_arithmetic_ops.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify -Wno-string-plus-int %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify -Wno-string-plus-int -Wno-tautological-pointer-compare %s #include <stddef.h> void f() { diff --git a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp index 9671353907c76..60b4670b3a5ec 100644 --- a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp +++ b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fblocks -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-pointer-compare -fblocks -std=c++11 -verify %s void foo() { int a; diff --git a/test/SemaCXX/old-style-cast.cpp b/test/SemaCXX/old-style-cast.cpp new file mode 100644 index 0000000000000..73a78e40ac353 --- /dev/null +++ b/test/SemaCXX/old-style-cast.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -Wold-style-cast %s + +void test1() { + long x = (long)12; // expected-warning {{use of old-style cast}} + (long)x; // expected-warning {{use of old-style cast}} expected-warning {{expression result unused}} + (void**)x; // expected-warning {{use of old-style cast}} expected-warning {{expression result unused}} + long y = static_cast<long>(12); + (void)y; + typedef void VOID; + (VOID)y; +} diff --git a/test/SemaCXX/operator-arrow-depth.cpp b/test/SemaCXX/operator-arrow-depth.cpp index 3e2ba8e45228a..769dae0d2461e 100644 --- a/test/SemaCXX/operator-arrow-depth.cpp +++ b/test/SemaCXX/operator-arrow-depth.cpp @@ -9,7 +9,7 @@ template<int N> struct A { template<int N> struct B { A<N-1> operator->(); // expected-note +{{'operator->' declared here produces an object of type 'A<}} #if MAX != 2 - // expected-note-re@-2 {{(skipping (120|2) 'operator->'s in backtrace)}} + // expected-note-re@-2 {{(skipping {{120|2}} 'operator->'s in backtrace)}} #endif }; @@ -22,5 +22,5 @@ A<MAX/2> good; int n = good->n; B<MAX/2 + 1> bad; -int m = bad->n; // expected-error-re {{use of 'operator->' on type 'B<(2|10|128) / 2 \+ 1>' would invoke a sequence of more than (2|10|128) 'operator->' calls}} +int m = bad->n; // expected-error-re {{use of 'operator->' on type 'B<{{2|10|128}} / 2 + 1>' would invoke a sequence of more than {{2|10|128}} 'operator->' calls}} // expected-note@-1 {{use -foperator-arrow-depth=N to increase 'operator->' limit}} diff --git a/test/SemaCXX/overload-0x.cpp b/test/SemaCXX/overload-0x.cpp index 677d16a32c121..1c185a5725bd6 100644 --- a/test/SemaCXX/overload-0x.cpp +++ b/test/SemaCXX/overload-0x.cpp @@ -1,7 +1,11 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s namespace test0 { - struct A { // expected-note {{candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'const test0::A', but method is not marked const}} expected-note {{candidate function (the implicit move assignment operator) not viable: 'this' argument has type 'const test0::A', but method is not marked const}} + struct A { // expected-note {{candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'const test0::A', but method is not marked const}} +#if __cplusplus >= 201103L + // expected-note@-2 {{candidate function (the implicit move assignment operator) not viable: 'this' argument has type 'const test0::A', but method is not marked const}} +#endif A &operator=(void*); // expected-note {{candidate function not viable: 'this' argument has type 'const test0::A', but method is not marked const}} }; @@ -9,3 +13,79 @@ namespace test0 { a = "help"; // expected-error {{no viable overloaded '='}} } } + +namespace PR16314 { + void f(char*); + int &f(...); + void x() + { + int &n = f("foo"); +#if __cplusplus < 201103L + // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}} + // expected-error@-3 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'void'}} +#endif + } +} + +namespace warn_if_best { + int f(char *); + void f(double); + void x() + { + int n = f("foo"); +#if __cplusplus < 201103L + // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}} +#else + // expected-warning@-4 {{ISO C++11 does not allow conversion from string literal to 'char *'}} +#endif + } +} + +namespace userdefined_vs_illformed { + struct X { X(const char *); }; + + void *f(char *p); // best for C++03 + double f(X x); // best for C++11 + void g() + { + double d = f("foo"); +#if __cplusplus < 201103L + // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}} + // expected-error@-3 {{cannot initialize a variable of type 'double' with an rvalue of type 'void *'}} +#endif + } +} + +namespace sfinae_test { + int f(int, char*); + + template<int T> + struct S { typedef int type; }; + + template<> + struct S<sizeof(int)> { typedef void type; }; + + // C++11: SFINAE failure + // C++03: ok + template<typename T> int cxx11_ignored(T, typename S<sizeof(f(T(), "foo"))>::type *); +#if __cplusplus < 201103L + // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}} +#else + // expected-note@-4 {{candidate template ignored: substitution failure}} +#endif + + // C++11: better than latter + // C++03: worse than latter + template<typename T> void g(T, ...); + template<typename T> int g(T, typename S<sizeof(f(T(), "foo"))>::type *); +#if __cplusplus < 201103L + // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}} +#endif + + int a = cxx11_ignored(0, 0); + int b = g(0, 0); +#if __cplusplus >= 201103L + // expected-error@-3 {{no matching function for call to 'cxx11_ignored'}} + // expected-error@-3 {{cannot initialize a variable of type 'int' with an rvalue of type 'void'}} +#endif +} diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 615b10a439715..19ce14481f8ef 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +// RUN: %clang_cc1 -pedantic -verify %s int* f(int) { return 0; } float* f(float) { return 0; } void f(); @@ -580,3 +580,31 @@ namespace PR12931 { void f(const volatile int &, int); void g() { f(0, 0); } } + +void test5() { + struct { + typedef void F1(int); + typedef void F2(double); + operator F1*(); // expected-note{{conversion candidate}} + operator F2*(); // expected-note{{conversion candidate}} + } callable; + callable(); // expected-error{{no matching function for call}} +} + +namespace PR20218 { + void f(void (*const &)()); // expected-note 2{{candidate}} + void f(void (&&)()) = delete; // expected-note 2{{candidate}} expected-warning 2{{extension}} + void g(void (&&)()) = delete; // expected-note 2{{candidate}} expected-warning 2{{extension}} + void g(void (*const &)()); // expected-note 2{{candidate}} + + void x(); + typedef void (&fr)(); + struct Y { operator fr(); } y; + + void h() { + f(x); // expected-error {{ambiguous}} + g(x); // expected-error {{ambiguous}} + f(y); // expected-error {{ambiguous}} + g(y); // expected-error {{ambiguous}} + } +} diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 99105cb5b60bc..feb7c716ff008 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -452,3 +452,70 @@ namespace PR7681 { Result = 1; // expected-error {{no viable overloaded '='}} // expected-note {{type 'PointerUnion<int *, float *>' is incomplete}} } } + +namespace PR14995 { + struct B {}; + template<typename ...T> void operator++(B, T...) {} + + void f() { + B b; + b++; // ok + ++b; // ok + } + + template<typename... T> + struct C { + void operator-- (T...) {} + }; + + void g() { + C<int> postfix; + C<> prefix; + postfix--; // ok + --prefix; // ok + } + + struct D {}; + template<typename T> void operator++(D, T) {} + + void h() { + D d; + d++; // ok + ++d; // expected-error{{cannot increment value of type 'PR14995::D'}} + } + + template<typename...T> struct E { + void operator++(T...) {} // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'char')}} + }; + + E<char> e; // expected-note {{in instantiation of template class 'PR14995::E<char>' requested here}} + + struct F { + template<typename... T> + int operator++ (T...) {} + }; + + int k1 = F().operator++(0, 0); + int k2 = F().operator++('0'); + // expected-error@-5 {{overloaded 'operator++' must be a unary or binary operator}} + // expected-note@-3 {{in instantiation of function template specialization 'PR14995::F::operator++<int, int>' requested here}} + // expected-error@-4 {{no matching member function for call to 'operator++'}} + // expected-note@-8 {{candidate template ignored: substitution failure}} + // expected-error@-9 {{parameter of overloaded post-increment operator must have type 'int' (not 'char')}} + // expected-note@-6 {{in instantiation of function template specialization 'PR14995::F::operator++<char>' requested here}} + // expected-error@-7 {{no matching member function for call to 'operator++'}} + // expected-note@-12 {{candidate template ignored: substitution failure}} +} // namespace PR14995 + +namespace ConversionVersusTemplateOrdering { + struct A { + operator short() = delete; + template <typename T> operator T(); + } a; + struct B { + template <typename T> operator T(); + operator short() = delete; + } b; + int x = a; + int y = b; +} diff --git a/test/SemaCXX/pr13394-crash-on-invalid.cpp b/test/SemaCXX/pr13394-crash-on-invalid.cpp index 841e3c203402c..304ee92f6a8da 100644 --- a/test/SemaCXX/pr13394-crash-on-invalid.cpp +++ b/test/SemaCXX/pr13394-crash-on-invalid.cpp @@ -8,12 +8,12 @@ namespace stretch_v1 { } namespace gatekeeper_v1 { namespace gatekeeper_factory_v1 { - struct closure_t { // expected-note {{'closure_t' declared here}} + struct closure_t { // expected-note {{'closure_t' declared here}} expected-note {{'gatekeeper_factory_v1::closure_t' declared here}} gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean simply 'closure_t'?}} }; } // FIXME: Typo correction should remove the 'gatekeeper_v1::' name specifier - gatekeeper_v1::closure_t *x; // expected-error-re {{no type named 'closure_t' in namespace 'gatekeeper_v1'$}} + gatekeeper_v1::closure_t *x; // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean 'gatekeeper_factory_v1::closure_t'}} } namespace Foo { diff --git a/test/SemaCXX/pr18284-crash-on-invalid.cpp b/test/SemaCXX/pr18284-crash-on-invalid.cpp new file mode 100644 index 0000000000000..5b1cb21f4bb6b --- /dev/null +++ b/test/SemaCXX/pr18284-crash-on-invalid.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// Don't crash (PR18284). + +namespace n1 { +class A { }; +class C { A a; }; + +A::RunTest() {} // expected-error {{C++ requires a type specifier for all declarations}} + +void f() { + new C; +} +} // namespace n1 + +namespace n2 { +class A { }; +class C : public A { }; + +A::RunTest() {} // expected-error {{C++ requires a type specifier for all declarations}} + +void f() { + new C; +} +} // namespace n2 diff --git a/test/SemaCXX/pr9812.c b/test/SemaCXX/pr9812.c new file mode 100644 index 0000000000000..cbbe44ba7ca0d --- /dev/null +++ b/test/SemaCXX/pr9812.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define bool _Bool +int test1(int argc, char** argv) +{ + bool signed; // expected-error {{'bool' cannot be signed or unsigned}} expected-warning {{declaration does not declare anything}} + + return 0; +} +#undef bool + +typedef int bool; + +int test2(int argc, char** argv) +{ + bool signed; // expected-error {{'type-name' cannot be signed or unsigned}} expected-warning {{declaration does not declare anything}} + _Bool signed; // expected-error {{'_Bool' cannot be signed or unsigned}} expected-warning {{declaration does not declare anything}} + + return 0; +} + diff --git a/test/SemaCXX/pr9812.cpp b/test/SemaCXX/pr9812.cpp new file mode 100644 index 0000000000000..2cd0bede02012 --- /dev/null +++ b/test/SemaCXX/pr9812.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int test(int, char**) +{ + bool signed; // expected-error {{'bool' cannot be signed or unsigned}} expected-warning {{declaration does not declare anything}} + + return 0; +} + diff --git a/test/SemaCXX/pragma-init_seg.cpp b/test/SemaCXX/pragma-init_seg.cpp new file mode 100644 index 0000000000000..e18d0e6814afc --- /dev/null +++ b/test/SemaCXX/pragma-init_seg.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple i386-apple-darwin13.3.0 + +#ifndef __APPLE__ +#pragma init_seg(L".my_seg") // expected-warning {{expected 'compiler', 'lib', 'user', or a string literal}} +#pragma init_seg( // expected-warning {{expected 'compiler', 'lib', 'user', or a string literal}} +#pragma init_seg asdf // expected-warning {{missing '('}} +#pragma init_seg) // expected-warning {{missing '('}} +#pragma init_seg("a" "b") // no warning +#pragma init_seg("a", "b") // expected-warning {{missing ')'}} +#pragma init_seg("a") asdf // expected-warning {{extra tokens at end of '#pragma init_seg'}} +#pragma init_seg("\x") // expected-error {{\x used with no following hex digits}} +#pragma init_seg("a" L"b") // expected-warning {{expected non-wide string literal in '#pragma init_seg'}} + +#pragma init_seg(compiler) +#else +#pragma init_seg(compiler) // expected-warning {{'#pragma init_seg' is only supported when targeting a Microsoft environment}} +#endif + +int f(); +int __declspec(thread) x = f(); // expected-error {{initializer for thread-local variable must be a constant expression}} diff --git a/test/SemaCXX/pragma-optimize.cpp b/test/SemaCXX/pragma-optimize.cpp new file mode 100644 index 0000000000000..0f03b81f5fffc --- /dev/null +++ b/test/SemaCXX/pragma-optimize.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s + +#pragma clang optimize off + +// This is a macro definition and therefore its text is not present after +// preprocessing. The pragma has no effect here. +#define CREATE_FUNC(name) \ +int name (int param) { \ + return param; \ +} \ + +// This is a declaration and therefore it is not decorated with `optnone`. +extern int foo(int a, int b); +// CHECK-DAG: @_Z3fooii{{.*}} [[ATTRFOO:#[0-9]+]] + +// This is a definition and therefore it will be decorated with `optnone`. +int bar(int x, int y) { + for(int i = 0; i < x; ++i) + y += x; + return y + foo(x, y); +} +// CHECK-DAG: @_Z3barii{{.*}} [[ATTRBAR:#[0-9]+]] + +// The function "int created (int param)" created by the macro invocation +// is also decorated with the `optnone` attribute because it is within a +// region of code affected by the functionality (not because of the position +// of the macro definition). +CREATE_FUNC (created) +// CHECK-DAG: @_Z7createdi{{.*}} [[ATTRCREATED:#[0-9]+]] + +class MyClass { + public: + // The declaration of the method is not decorated with `optnone`. + int method(int blah); +}; + +// The definition of the method instead is decorated with `optnone`. +int MyClass::method(int blah) { + return blah + 1; +} +// CHECK-DAG: @_ZN7MyClass6methodEi{{.*}} [[ATTRMETHOD:#[0-9]+]] + +// A template declaration will not be decorated with `optnone`. +template <typename T> T twice (T param); + +// The template definition will be decorated with the attribute `optnone`. +template <typename T> T thrice (T param) { + return 3 * param; +} + +// This function definition will not be decorated with `optnone` because the +// attribute would conflict with `always_inline`. +int __attribute__((always_inline)) baz(int z) { + return foo(z, 2); +} +// CHECK-DAG: @_Z3bazi{{.*}} [[ATTRBAZ:#[0-9]+]] + +#pragma clang optimize on + +// The function "int wombat(int param)" created by the macro is not +// decorated with `optnone`, because the pragma applies its effects only +// after preprocessing. The position of the macro definition is not +// relevant. +CREATE_FUNC (wombat) +// CHECK-DAG: @_Z6wombati{{.*}} [[ATTRWOMBAT:#[0-9]+]] + +// This instantiation of the "twice" template function with a "float" type +// will not have an `optnone` attribute because the template declaration was +// not affected by the pragma. +float container (float par) { + return twice(par); +} +// CHECK-DAG: @_Z9containerf{{.*}} [[ATTRCONTAINER:#[0-9]+]] +// CHECK-DAG: @_Z5twiceIfET_S0_{{.*}} [[ATTRTWICE:#[0-9]+]] + +// This instantiation of the "thrice" template function with a "float" type +// will have an `optnone` attribute because the template definition was +// affected by the pragma. +float container2 (float par) { + return thrice(par); +} +// CHECK-DAG: @_Z10container2f{{.*}} [[ATTRCONTAINER2:#[0-9]+]] +// CHECK-DAG: @_Z6thriceIfET_S0_{{.*}} [[ATTRTHRICEFLOAT:#[0-9]+]] + + +// A template specialization is a new definition and it will not be +// decorated with an `optnone` attribute because it is now outside of the +// affected region. +template<> int thrice(int par) { + return (par << 1) + par; +} +int container3 (int par) { + return thrice(par); +} +// CHECK-DAG: @_Z10container3i{{.*}} [[ATTRCONTAINER3:#[0-9]+]] +// CHECK-DAG: @_Z6thriceIiET_S0_{{.*}} [[ATTRTHRICEINT:#[0-9]+]] + + +// Check for both noinline and optnone on each function that should have them. +// CHECK-DAG: attributes [[ATTRBAR]] = { {{.*}}noinline{{.*}}optnone{{.*}} } +// CHECK-DAG: attributes [[ATTRCREATED]] = { {{.*}}noinline{{.*}}optnone{{.*}} } +// CHECK-DAG: attributes [[ATTRMETHOD]] = { {{.*}}noinline{{.*}}optnone{{.*}} } +// CHECK-DAG: attributes [[ATTRTHRICEFLOAT]] = { {{.*}}noinline{{.*}}optnone{{.*}} } + +// Check that the other functions do NOT have optnone. +// CHECK-DAG-NOT: attributes [[ATTRFOO]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRBAZ]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRWOMBAT]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRCONTAINER]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRTWICE]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRCONTAINER2]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRCONTAINER3]] = { {{.*}}optnone{{.*}} } +// CHECK-DAG-NOT: attributes [[ATTRTHRICEINT]] = { {{.*}}optnone{{.*}} } diff --git a/test/SemaCXX/pragma-vtordisp.cpp b/test/SemaCXX/pragma-vtordisp.cpp new file mode 100644 index 0000000000000..49841c51ef054 --- /dev/null +++ b/test/SemaCXX/pragma-vtordisp.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -fms-extensions -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s + +struct A { int a; }; + +#pragma vtordisp(pop) // expected-warning {{#pragma vtordisp(pop, ...) failed: stack empty}} +#pragma vtordisp(push, 0) +#pragma vtordisp(push, 1) +#pragma vtordisp(push, 2) +struct B : virtual A { int b; }; +#pragma vtordisp(pop) +#pragma vtordisp(pop) +#pragma vtordisp(pop) +#pragma vtordisp(pop) // expected-warning {{#pragma vtordisp(pop, ...) failed: stack empty}} + +#pragma vtordisp(push, 3) // expected-warning {{expected integer between 0 and 2 inclusive in '#pragma vtordisp' - ignored}} +#pragma vtordisp() + +#define ONE 1 +#pragma vtordisp(push, ONE) +#define TWO 1 +#pragma vtordisp(push, TWO) + +// Test a reset. +#pragma vtordisp() +#pragma vtordisp(pop) // expected-warning {{#pragma vtordisp(pop, ...) failed: stack empty}} + +#pragma vtordisp( // expected-warning {{unknown action for '#pragma vtordisp' - ignored}} +#pragma vtordisp(asdf) // expected-warning {{unknown action for '#pragma vtordisp' - ignored}} +#pragma vtordisp(,) // expected-warning {{unknown action for '#pragma vtordisp' - ignored}} +#pragma vtordisp // expected-warning {{missing '(' after '#pragma vtordisp' - ignoring}} +#pragma vtordisp(3) // expected-warning {{expected integer between 0 and 2 inclusive in '#pragma vtordisp' - ignored}} +#pragma vtordisp(), stuff // expected-warning {{extra tokens}} + +struct C { +// FIXME: Our implementation based on token insertion makes it impossible for +// the pragma to appear everywhere we should support it. +//#pragma vtordisp() + struct D : virtual A { + }; +}; diff --git a/test/SemaCXX/pragma-weak.cpp b/test/SemaCXX/pragma-weak.cpp index 057cf6b463f39..c1ff2062fcfa2 100644 --- a/test/SemaCXX/pragma-weak.cpp +++ b/test/SemaCXX/pragma-weak.cpp @@ -6,3 +6,6 @@ extern "C" { void foo() { }; } + +extern "C" int Test; +#pragma weak test = Test diff --git a/test/SemaCXX/primary-base.cpp b/test/SemaCXX/primary-base.cpp index 0b6aaef493cbf..d305aa3b72db8 100644 --- a/test/SemaCXX/primary-base.cpp +++ b/test/SemaCXX/primary-base.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify %s // expected-no-diagnostics class A { virtual void f(); }; class B : virtual A { }; diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index 23164fa42f325..8eef6f4182746 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -94,7 +94,7 @@ namespace a { void test_a() { 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'$}} + 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/references.cpp b/test/SemaCXX/references.cpp index 37fc2a856fd97..cfe7dc1f428b8 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -85,9 +85,19 @@ void test8(int& const,// expected-error{{'const' qualifier may not be applied to typedef int& intref; typedef intref& intrefref; // C++ DR 106: reference collapsing - typedef intref const intref_c; // okay. FIXME: how do we verify that this is the same type as intref? + typedef intref const intref_c; // expected-warning {{'const' qualifier on reference type 'intref' (aka 'int &') has no effect}} + typedef intref_c intref; // ok, same type + + typedef intref volatile intref; // expected-warning {{'volatile' qualifier on reference type 'intref' (aka 'int &') has no effect}} + typedef intref _Atomic intref; // expected-warning {{'_Atomic' qualifier on reference type 'intref' (aka 'int &') has no effect}} + + void restrict_ref(__restrict intref); // ok + void restrict_ref(int &__restrict); // ok } +template<typename T> int const_param(const T) {} +int const_ref_param = const_param<int&>(const_ref_param); // no-warning + class string { char *Data; diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index a4bc4325e6550..4284032d9ba9b 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -96,12 +96,12 @@ void memptrs() void (structure::*psf)() = 0; (void)reinterpret_cast<int (structure::*)()>(psf); - (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'const int structure::*' to 'void (structure::*)()' is not allowed}} - (void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (structure::*)()' to 'int structure::*' is not allowed}} + (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error-re {{reinterpret_cast from 'const int structure::*' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}} + (void)reinterpret_cast<int structure::*>(psf); // expected-error-re {{reinterpret_cast from 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' to 'int structure::*' is not allowed}} // Cannot cast from integers to member pointers, not even the null pointer // literal. - (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (structure::*)()' is not allowed}} + (void)reinterpret_cast<void (structure::*)()>(0); // expected-error-re {{reinterpret_cast from 'int' to 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' is not allowed}} (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int structure::*' is not allowed}} } diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp index 617de0089585d..531dc23995d27 100644 --- a/test/SemaCXX/return-noreturn.cpp +++ b/test/SemaCXX/return-noreturn.cpp @@ -40,6 +40,14 @@ namespace abort_struct_complex_cfgs { switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } } + // FIXME: detect noreturn destructors triggered by calls to delete. + int f7(int x) { + switch (x) default: L1: L2: case 4: { + pr6884_abort_struct *p = new pr6884_abort_struct(); + delete p; + } + } // expected-warning {{control reaches end of non-void function}} + // Test that these constructs work even when extraneous blocks are created // before and after the switch due to implicit destructors. int g1(int x) { @@ -138,3 +146,25 @@ void PR9412_f() { PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<0>' requested here}} } +#if __cplusplus >= 201103L +namespace LambdaVsTemporaryDtor { + struct Y { ~Y(); }; + struct X { template<typename T> X(T, Y = Y()) {} }; + + struct Fatal { ~Fatal() __attribute__((noreturn)); }; + struct FatalCopy { FatalCopy(); FatalCopy(const FatalCopy&, Fatal F = Fatal()); }; + + void foo(); + + int bar() { + X work([](){ Fatal(); }); + foo(); + } // expected-warning {{control reaches end of non-void function}} + + int baz() { + FatalCopy fc; + X work([fc](){}); + foo(); + } // ok, initialization of lambda does not return +} +#endif diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp index fbbaf836f1abf..7670798ecb9c1 100644 --- a/test/SemaCXX/return-stack-addr.cpp +++ b/test/SemaCXX/return-stack-addr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s int* ret_local() { int x = 1; @@ -108,6 +108,11 @@ int* ret_cpp_const_cast(const int x) { return const_cast<int*>(&x); // expected-warning {{address of stack memory}} } +struct A { virtual ~A(); }; struct B : A {}; +A* ret_cpp_dynamic_cast(B b) { + return dynamic_cast<A*>(&b); // expected-warning {{address of stack memory}} +} + // PR 7999 - handle the case where a field is itself a reference. template <typename T> struct PR7999 { PR7999(T& t) : value(t) {} @@ -137,5 +142,17 @@ namespace PR8774 { } } -// TODO: test case for dynamic_cast. clang does not yet have -// support for C++ classes to write such a test case. +// Don't warn about returning a local variable from a surrounding function if +// we're within a lambda-expression. +void ret_from_lambda() { + int a; + int &b = a; + (void) [&]() -> int& { return a; }; + (void) [&]() -> int& { return b; }; + (void) [=]() mutable -> int& { return a; }; + (void) [=]() mutable -> int& { return b; }; + (void) [&]() -> int& { int a; return a; }; // expected-warning {{reference to stack}} + (void) [=]() -> int& { int a; return a; }; // expected-warning {{reference to stack}} + (void) [&]() -> int& { int &a = b; return a; }; + (void) [=]() mutable -> int& { int &a = b; return a; }; +} diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index 580f0a7233e2c..98dbd51f58068 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -102,3 +102,13 @@ namespace return_has_expr { } }; } + +// rdar://15366494 +// pr17759 +namespace ctor_returns_void { + void f() {} + struct S { + S() { return f(); }; // expected-error {{constructor 'S' must not return void expression}} + ~S() { return f(); } // expected-error {{destructor '~S' must not return void expression}} + }; +} diff --git a/test/SemaCXX/rval-references-examples.cpp b/test/SemaCXX/rval-references-examples.cpp index 110ae26fb5d29..8a5b562bbb982 100644 --- a/test/SemaCXX/rval-references-examples.cpp +++ b/test/SemaCXX/rval-references-examples.cpp @@ -4,7 +4,7 @@ template<typename T> class unique_ptr { T *ptr; - unique_ptr(const unique_ptr&) = delete; // expected-note 3{{function has been explicitly marked deleted here}} + unique_ptr(const unique_ptr&) = delete; // expected-note 3{{'unique_ptr' has been explicitly marked deleted here}} unique_ptr &operator=(const unique_ptr&) = delete; // expected-note{{candidate function has been explicitly deleted}} public: unique_ptr() : ptr(0) { } diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index 90c9317ecdfb8..dc15dc8b3e600 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -1,6 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -fcxx-exceptions %s -Wno-unreachable-code // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -fcxx-exceptions -std=gnu++11 %s -Wno-unreachable-code +namespace testInvalid { +Invalid inv; // expected-error {{unknown type name}} +// Make sure this doesn't assert. +void fn() +{ + int c = 0; + if (inv) +Here: ; + goto Here; +} +} + namespace test0 { struct D { ~D(); }; @@ -226,7 +238,7 @@ namespace test12 { static void *ips[] = { &&l0 }; const C c0 = 17; l0: // expected-note {{possible target of indirect goto}} - const C &c1 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}} + const C &c1 = 42; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} const C &c2 = c0; goto *ip; // expected-error {{indirect goto might cross protected scopes}} } @@ -241,7 +253,7 @@ namespace test13 { void f(void **ip) { static void *ips[] = { &&l0 }; l0: // expected-note {{possible target of indirect goto}} - const int &c1 = C(1).i; // expected-note {{jump exits scope of variable with non-trivial destructor}} + const int &c1 = C(1).i; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} goto *ip; // expected-error {{indirect goto might cross protected scopes}} } } @@ -295,15 +307,137 @@ x: return s.get(); } #endif -// This test must be last, because the error prohibits further jump diagnostics. -namespace testInvalid { -Invalid inv; // expected-error {{unknown type name}} -// Make sure this doesn't assert. -void fn() -{ - int c = 0; - if (inv) -Here: ; - goto Here; +namespace test18 { + struct A { ~A(); }; + struct B { const int &r; const A &a; }; + int f() { + void *p = &&x; + const A a = A(); + x: + B b = { 0, a }; // ok + goto *p; + } + int g() { + void *p = &&x; + x: // expected-note {{possible target of indirect goto}} + B b = { 0, A() }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} + goto *p; // expected-error {{indirect goto might cross protected scopes}} + } +} + +#if __cplusplus >= 201103L +namespace std { + typedef decltype(sizeof(int)) size_t; + template<typename T> struct initializer_list { + const T *begin; + size_t size; + initializer_list(const T *, size_t); + }; +} +namespace test19 { + struct A { ~A(); }; + + int f() { + void *p = &&x; + A a; + x: // expected-note {{possible target of indirect goto}} + std::initializer_list<A> il = { a }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} + goto *p; // expected-error {{indirect goto might cross protected scopes}} + } +} + +namespace test20 { + struct A { ~A(); }; + struct B { + const A &a; + }; + + int f() { + void *p = &&x; + A a; + x: + std::initializer_list<B> il = { + a, + a + }; + goto *p; + } + int g() { + void *p = &&x; + A a; + x: // expected-note {{possible target of indirect goto}} + std::initializer_list<B> il = { + a, + { A() } // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} + }; + goto *p; // expected-error {{indirect goto might cross protected scopes}} + } } +#endif + +namespace test21 { + template<typename T> void f() { + goto x; // expected-error {{protected scope}} + T t; // expected-note {{bypasses}} + x: return; + } + + template void f<int>(); + struct X { ~X(); }; + template void f<X>(); // expected-note {{instantiation of}} +} + +namespace PR18217 { + typedef int *X; + + template <typename T> + class MyCl { + T mem; + }; + + class Source { + MyCl<X> m; + public: + int getKind() const; + }; + + bool b; + template<typename TT> + static void foo(const Source &SF, MyCl<TT *> Source::*m) { + switch (SF.getKind()) { + case 1: return; + case 2: break; + case 3: + case 4: return; + }; + if (b) { + auto &y = const_cast<MyCl<TT *> &>(SF.*m); // expected-warning 0-1{{extension}} + } + } + + int Source::getKind() const { + foo(*this, &Source::m); + return 0; + } +} + +namespace test_recovery { + // Test that jump scope checking recovers when there are unspecified errors + // in the function declaration or body. + + void test(nexist, int c) { // expected-error {{}} + nexist_fn(); // expected-error {{}} + goto nexist_label; // expected-error {{use of undeclared label}} + goto a0; // expected-error {{goto into protected scope}} + int a = 0; // expected-note {{jump bypasses variable initialization}} + a0:; + + switch (c) { + case $: // expected-error {{}} + case 0: + int x = 56; // expected-note {{jump bypasses variable initialization}} + case 1: // expected-error {{switch case is in protected scope}} + x = 10; + } + } } diff --git a/test/SemaCXX/sourceranges.cpp b/test/SemaCXX/sourceranges.cpp index 1f25d5bce93ca..9ba003aa204a7 100644 --- a/test/SemaCXX/sourceranges.cpp +++ b/test/SemaCXX/sourceranges.cpp @@ -12,7 +12,7 @@ enum B {}; typedef int C; } -// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> ImplicitConstrArray 'foo::A [2]' +// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]' static foo::A ImplicitConstrArray[2]; int main() { @@ -28,3 +28,12 @@ foo::A getName() { // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A' return foo::A(); } + +void destruct(foo::A *a1, foo::A *a2, P<int> *p1) { + // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:8> '<bound member function type>' ->~A + a1->~A(); + // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:16> '<bound member function type>' ->~A + a2->foo::A::~A(); + // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:13> '<bound member function type>' ->~P + p1->~P<int>(); +} diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp index 4a7560ba5b6a2..7de4d07b50b8e 100644 --- a/test/SemaCXX/static-assert.cpp +++ b/test/SemaCXX/static-assert.cpp @@ -48,3 +48,6 @@ template<typename T> struct StaticAssertProtected { struct X { ~X(); }; StaticAssertProtected<int> sap1; StaticAssertProtected<X> sap2; // expected-note {{instantiation}} + +static_assert(true); // expected-warning {{C++1z extension}} +static_assert(false); // expected-error-re {{failed{{$}}}} expected-warning {{extension}} diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp index 7fb016ea86d8b..06fd8636e5d6d 100644 --- a/test/SemaCXX/static-cast.cpp +++ b/test/SemaCXX/static-cast.cpp @@ -9,6 +9,8 @@ struct F : public C1 {}; // Single path to B with virtual. struct G1 : public B {}; struct G2 : public B {}; struct H : public G1, public G2 {}; // Ambiguous path to B. +struct I; // Incomplete. +struct J; // Incomplete. enum Enum { En1, En2 }; enum Onom { On1, On2 }; @@ -131,6 +133,7 @@ void t_529_9() // Bad code below (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'H' to pointer to member of base class 'A':}} (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}} + (void)static_cast<int I::*>((int J::*)0); // expected-error {{static_cast from 'int J::*' to 'int I::*' is not allowed}} } // PR 5261 - static_cast should instantiate template if possible @@ -192,6 +195,6 @@ namespace PR6072 { (void)static_cast<void (A::*)()>(&B::f); (void)static_cast<void (B::*)()>(&B::f); (void)static_cast<void (C::*)()>(&B::f); - (void)static_cast<void (D::*)()>(&B::f); // expected-error{{address of overloaded function 'f' cannot be static_cast to type 'void (PR6072::D::*)()'}} + (void)static_cast<void (D::*)()>(&B::f); // expected-error-re{{address of overloaded function 'f' cannot be static_cast to type 'void (PR6072::D::*)(){{( __attribute__\(\(thiscall\)\))?}}'}} } } diff --git a/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp b/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp new file mode 100644 index 0000000000000..9a16f2b4b402f --- /dev/null +++ b/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++11 -Wimplicit-fallthrough %s + +void fallthrough_in_blocks() { + void (^block)() = ^{ + int x = 0; + switch (x) { + case 0: + x++; + [[clang::fallthrough]]; // no diagnostics + case 1: + x++; + default: // \ + expected-warning{{unannotated fall-through between switch labels}} \ + expected-note{{insert 'break;' to avoid fall-through}} + break; + } + }; + block(); +} diff --git a/test/SemaCXX/switch-implicit-fallthrough.cpp b/test/SemaCXX/switch-implicit-fallthrough.cpp index d7959238c6b36..0bc43cdbd45b2 100644 --- a/test/SemaCXX/switch-implicit-fallthrough.cpp +++ b/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -229,6 +229,59 @@ int fallthrough_covered_enums(Enum e) { return n; } +// Fallthrough annotations in local classes used to generate "fallthrough +// annotation does not directly precede switch label" warning. +void fallthrough_in_local_class() { + class C { + void f(int x) { + switch (x) { + case 0: + x++; + [[clang::fallthrough]]; // no diagnostics + case 1: + x++; + default: // \ + expected-warning{{unannotated fall-through between switch labels}} \ + expected-note{{insert 'break;' to avoid fall-through}} + break; + } + } + }; +} + +// Fallthrough annotations in lambdas used to generate "fallthrough +// annotation does not directly precede switch label" warning. +void fallthrough_in_lambda() { + (void)[] { + int x = 0; + switch (x) { + case 0: + x++; + [[clang::fallthrough]]; // no diagnostics + case 1: + x++; + default: // \ + expected-warning{{unannotated fall-through between switch labels}} \ + expected-note{{insert 'break;' to avoid fall-through}} + break; + } + }; +} + +namespace PR18983 { + void fatal() __attribute__((noreturn)); + int num(); + void test() { + switch (num()) { + case 1: + fatal(); + // Don't issue a warning. + case 2: + break; + } + } +} + int fallthrough_targets(int n) { [[clang::fallthrough]]; // expected-error{{fallthrough annotation is outside switch statement}} @@ -247,21 +300,3 @@ int fallthrough_targets(int n) { } return n; } - -// Fallthrough annotations in local classes used to generate "fallthrough -// annotation does not directly precede switch label" warning. -void fallthrough_in_local_class() { - class C { - void f(int x) { - switch (x) { - case 0: - x++; - [[clang::fallthrough]]; // no diagnostics - case 1: - x++; - break; - } - } - }; -} - diff --git a/test/SemaCXX/template-implicit-vars.cpp b/test/SemaCXX/template-implicit-vars.cpp new file mode 100644 index 0000000000000..25d35fbdb84f5 --- /dev/null +++ b/test/SemaCXX/template-implicit-vars.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -ast-dump | FileCheck %s +template<typename T> +void f(T t) { + T a[] = {t}; + for (auto x : a) {} +} + +void g() { + f(1); +} +// CHECK: VarDecl {{.*}} implicit used __range +// CHECK: VarDecl {{.*}} implicit used __range +// CHECK: VarDecl {{.*}} implicit used __begin +// CHECK: VarDecl {{.*}} implicit used __end diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp index f7e3433a76086..cf5e659660eb0 100644 --- a/test/SemaCXX/trailing-return-0x.cpp +++ b/test/SemaCXX/trailing-return-0x.cpp @@ -17,7 +17,9 @@ auto f() -> int return 0; } -auto g(); // expected-error{{return without trailing return type}} +auto g(); // expected-error{{return without trailing return type; deduced return types are a C++1y extension}} +decltype(auto) g2(); // expected-warning{{extension}} expected-error-re{{{{^}}deduced return types are a C++1y extension}} +auto badness = g2(); int h() -> int; // expected-error{{trailing return type must specify return type 'auto', not 'int'}} diff --git a/test/SemaCXX/type-definition-in-specifier.cpp b/test/SemaCXX/type-definition-in-specifier.cpp index a614e6c2812ec..43443a00e44ba 100644 --- a/test/SemaCXX/type-definition-in-specifier.cpp +++ b/test/SemaCXX/type-definition-in-specifier.cpp @@ -13,13 +13,54 @@ struct S0 { int x; }; void f0() { typedef struct S1 { int x; } S1_typedef; - (void)((struct S2 { int x; }*)0); // expected-error{{can not be defined}} + (void)((struct S2 { int x; }*)0); // expected-error{{cannot be defined}} struct S3 { int x; } s3; - (void)static_cast<struct S4 { int x; } *>(0); // expected-error{{can not be defined}} + (void)static_cast<struct S4 { int x; } *>(0); // expected-error{{cannot be defined}} } struct S5 { int x; } f1() { return S5(); } // expected-error{{result type}} void f2(struct S6 { int x; } p); // expected-error{{parameter type}} + +struct pr19018 { + short foo6 (enum bar0 {qq} bar3); // expected-error{{cannot be defined in a parameter type}} +}; + +void pr19018_1 (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_1a (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}} +e19018_1 x2; // expected-error{{unknown type name 'e19018_1'}} + +void pr19018_2 (enum {qq} x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_3 (struct s19018_2 {int qq;} x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_4 (struct {int qq;} x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_5 (struct { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} +void pr19018_5 (struct s19018_2 { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} + +struct pr19018a { + static int xx; + void func1(enum t19018 {qq} x); // expected-error{{cannot be defined in a parameter type}} + void func2(enum t19018 {qq} x); // expected-error{{cannot be defined in a parameter type}} + void func3(enum {qq} x); // expected-error{{cannot be defined in a parameter type}} + void func4(struct t19018 {int qq;} x); // expected-error{{cannot be defined in a parameter type}} + void func5(struct {int qq;} x); // expected-error{{cannot be defined in a parameter type}} + void func6(struct { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} + void func7(struct t19018 { void qq(); } x); // expected-error{{cannot be defined in a parameter type}} + void func8(struct { int qq() { return xx; }; } x); // expected-error{{cannot be defined in a parameter type}} + void func9(struct t19018 { int qq() { return xx; }; } x); // expected-error{{cannot be defined in a parameter type}} +}; + +struct s19018b { + void func1 (enum en_2 {qq} x); // expected-error{{cannot be defined in a parameter type}} + en_2 x1; // expected-error{{unknown type name 'en_2'}} + void func2 (enum en_3 {qq} x); // expected-error{{cannot be defined in a parameter type}} + enum en_3 x2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} \ + // expected-error{{field has incomplete type 'enum en_3'}} \ + // expected-note{{forward declaration of 'en_3'}} +}; + +struct pr18963 { + short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}} + long foo5 (float foo6 = foo4); // expected-error{{use of undeclared identifier 'foo4'}} +}; diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 3e479215838e4..3b94ef0951ebf 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -112,6 +112,14 @@ struct HasNoThrowConstructor { HasNoThrowConstructor() throw(); }; struct HasNoThrowConstructorWithArgs { HasNoThrowConstructorWithArgs(HasCons i = HasCons(0)) throw(); }; +struct HasMultipleDefaultConstructor1 { + HasMultipleDefaultConstructor1() throw(); + HasMultipleDefaultConstructor1(int i = 0); +}; +struct HasMultipleDefaultConstructor2 { + HasMultipleDefaultConstructor2(int i = 0); + HasMultipleDefaultConstructor2() throw(); +}; struct HasNoThrowCopy { HasNoThrowCopy(const HasNoThrowCopy&) throw(); }; struct HasMultipleCopy { @@ -1475,6 +1483,10 @@ void has_nothrow_move_assign() { { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor))]; } { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign))]; } { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToDtor))]; } + + + { int arr[T(__is_nothrow_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign))]; } + { int arr[F(__is_nothrow_assignable(HasThrowMoveAssign, HasThrowMoveAssign))]; } } void has_trivial_move_assign() { @@ -1562,6 +1574,9 @@ 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))]; } + + { int arr[F(__has_nothrow_constructor(HasMultipleDefaultConstructor1))]; } + { int arr[F(__has_nothrow_constructor(HasMultipleDefaultConstructor2))]; } } void has_virtual_destructor() { @@ -1931,6 +1946,30 @@ void trivial_checks() TrivialMoveButNotCopy&&)))]; } } +void constructible_checks() { + { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs))]; } + { int arr[F(__is_nothrow_constructible(HasNoThrowConstructorWithArgs))]; } // MSVC doesn't look into default args and gets this wrong. + + { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs, HasCons))]; } + { int arr[T(__is_nothrow_constructible(HasNoThrowConstructorWithArgs, HasCons))]; } + + { int arr[T(__is_constructible(NonTrivialDefault))]; } + { int arr[F(__is_nothrow_constructible(NonTrivialDefault))]; } + + { int arr[T(__is_constructible(int))]; } + { int arr[T(__is_nothrow_constructible(int))]; } + + { int arr[F(__is_constructible(NonPOD))]; } + { int arr[F(__is_nothrow_constructible(NonPOD))]; } + + { int arr[T(__is_constructible(NonPOD, int))]; } + { int arr[F(__is_nothrow_constructible(NonPOD, int))]; } + + // PR19178 + { int arr[F(__is_constructible(Abstract))]; } + { int arr[F(__is_nothrow_constructible(Abstract))]; } +} + // Instantiation of __is_trivially_constructible template<typename T, typename ...Args> struct is_trivially_constructible { @@ -1956,6 +1995,7 @@ void is_trivially_constructible_test() { { int arr[F((is_trivially_constructible<int, int*>::value))]; } { int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; } { int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, int&>::value))]; } + { int arr[F((is_trivially_constructible<Abstract>::value))]; } // PR19178 } void array_rank() { diff --git a/test/SemaCXX/typeid-ref.cpp b/test/SemaCXX/typeid-ref.cpp index d01fd316854c3..7e5dbdd85adeb 100644 --- a/test/SemaCXX/typeid-ref.cpp +++ b/test/SemaCXX/typeid-ref.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s namespace std { class type_info; } @@ -7,6 +7,6 @@ struct X { }; void f() { // CHECK: @_ZTS1X = linkonce_odr constant - // CHECK: @_ZTI1X = linkonce_odr unnamed_addr constant + // CHECK: @_ZTI1X = linkonce_odr constant (void)typeid(X&); } diff --git a/test/SemaCXX/types_compatible_p.cpp b/test/SemaCXX/types_compatible_p.cpp index 4aa9a1cfa939b..29e06405adeae 100644 --- a/test/SemaCXX/types_compatible_p.cpp +++ b/test/SemaCXX/types_compatible_p.cpp @@ -1,5 +1,9 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s +// RUN: %clang_cc1 -fsyntax-only -x c %s -bool f() { - return __builtin_types_compatible_p(int, const int); // expected-error{{C++}} +// Test that GNU C extension __builtin_types_compatible_p() is not available in C++ mode. + +int f() { + return __builtin_types_compatible_p(int, const int); // expected-error{{expected '(' for function-style cast or type construction}} \ + // expected-error{{expected expression}} } diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp index 525d11b0a67b9..88a7073f99468 100644 --- a/test/SemaCXX/typo-correction-pt2.cpp +++ b/test/SemaCXX/typo-correction-pt2.cpp @@ -5,10 +5,19 @@ // attempt within a single file (which is to avoid having very broken files take // minutes to finally be rejected by the parser). +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 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'$}} + status = "OK"; // expected-error-re {{use of undeclared identifier 'status'{{$}}}} + return status; // expected-error-re {{use of undeclared identifier 'status'{{$}}}} } } @@ -33,7 +42,7 @@ struct T { }; // should be void T::f(); void f() { - data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}} + data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'{{$}}}} } namespace PR12287 { @@ -116,9 +125,9 @@ public: void testAccess() { Figure obj; switch (obj.type()) { // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}} - case SQUARE: // expected-error-re {{use of undeclared identifier 'SQUARE'$}} - case TRIANGLE: // expected-error-re {{use of undeclared identifier 'TRIANGLE'$}} - case CIRCE: // expected-error-re {{use of undeclared identifier 'CIRCE'$}} + case SQUARE: // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}} + case TRIANGLE: // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}} + case CIRCE: // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}} break; } } @@ -126,13 +135,13 @@ void testAccess() { long readline(const char *, char *, unsigned long); void assign_to_unknown_var() { - deadline_ = 1; // expected-error-re {{use of undeclared identifier 'deadline_'$}} + deadline_ = 1; // expected-error-re {{use of undeclared identifier 'deadline_'{{$}}}} } namespace no_ns_before_dot { namespace re2 {} void test() { - req.set_check(false); // expected-error-re {{use of undeclared identifier 'req'$}} + req.set_check(false); // expected-error-re {{use of undeclared identifier 'req'{{$}}}} } } @@ -199,3 +208,95 @@ template <> PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 }; // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \ // expected-error {{C++ requires a type specifier for all declarations}} } + +namespace PR18651 { +struct { + int x; +} a, b; + +int y = x; // expected-error-re {{use of undeclared identifier 'x'{{$}}}} +} + +namespace PR18685 { +template <class C, int I, int J> +class SetVector { + public: + SetVector() {} +}; + +template <class C, int I> +class SmallSetVector : public SetVector<C, I, 8> {}; + +class foo {}; +SmallSetVector<foo*, 2> fooSet; +} + +PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}} + +namespace shadowed_template { +template <typename T> class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}} +class Baz { + int Fizbin(); + // TODO: Teach the parser to recover from the typo correction instead of + // continuing to treat the template name as an implicit-int declaration. + Fizbin<int> qux; // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \ + // expected-error {{expected member name or ';' after declaration specifiers}} +}; +} + +namespace PR18852 { +void func() { + struct foo { + void bar() {} + }; + bar(); // expected-error-re {{use of undeclared identifier 'bar'{{$}}}} +} + +class Thread { + public: + void Start(); + static void Stop(); // expected-note {{'Thread::Stop' declared here}} +}; + +class Manager { + public: + void Start(int); // expected-note {{'Start' declared here}} + void Stop(int); // expected-note {{'Stop' declared here}} +}; + +void test(Manager *m) { + // Don't suggest Thread::Start as a correction just because it has the same + // (unqualified) name and accepts the right number of args; this is a method + // call on an object in an unrelated class. + m->Start(); // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}} + m->Stop(); // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}} + Stop(); // expected-error {{use of undeclared identifier 'Stop'; did you mean 'Thread::Stop'?}} +} + +} + +namespace std { +class bernoulli_distribution { + public: + double p() const; +}; +} +void test() { + // Make sure that typo correction doesn't suggest changing 'p' to + // 'std::bernoulli_distribution::p' as that is most likely wrong. + if (p) // expected-error-re {{use of undeclared identifier 'p'{{$}}}} + return; +} + +namespace PR19681 { + struct TypoA {}; + struct TypoB { + void test(); + private: + template<typename T> void private_memfn(T); // expected-note{{declared here}} + }; + void TypoB::test() { + // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn' + (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn); // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}} + } +} diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index 4047e6a18cee2..e8160b066de42 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -202,15 +202,6 @@ namespace ImplicitInt { }; } -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(); @@ -282,13 +273,13 @@ namespace b6956809_test1 { namespace b6956809_test2 { template<typename T> struct Err { typename T::error n; }; // expected-error{{type 'void *' cannot be used prior to '::' because it has no members}} struct S { - template<typename T> typename Err<T>::type method(T); // expected-note{{in instantiation of template class 'b6956809_test2::Err<void *>' requested here}} expected-note{{while substituting deduced template arguments into function template 'method' [with T = void *]}} + template<typename T> typename Err<T>::type method(T); // expected-note{{in instantiation of template class 'b6956809_test2::Err<void *>' requested here}} template<typename T> int method(T *); }; void test() { S s; - int k = s.methodd((void*)0); // expected-error{{no member named 'methodd' in 'b6956809_test2::S'; did you mean 'method'?}} + int k = s.methodd((void*)0); // expected-error{{no member named 'methodd' in 'b6956809_test2::S'; did you mean 'method'?}} expected-note{{while substituting deduced template arguments into function template 'method' [with T = void *]}} } } @@ -299,6 +290,6 @@ namespace CorrectTypo_has_reached_its_limit { int flibberdy(); // expected-note{{'flibberdy' declared here}} int no_correction() { return hibberdy() + // expected-error{{use of undeclared identifier 'hibberdy'; did you mean 'flibberdy'?}} - gibberdy(); // expected-error-re{{use of undeclared identifier 'gibberdy'$}} + gibberdy(); // expected-error-re{{use of undeclared identifier 'gibberdy'{{$}}}} }; } diff --git a/test/SemaCXX/undefined-inline.cpp b/test/SemaCXX/undefined-inline.cpp index ad719ae03abb6..18973ef8b79c8 100644 --- a/test/SemaCXX/undefined-inline.cpp +++ b/test/SemaCXX/undefined-inline.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple i686-pc-win32 -verify %s // PR14993 namespace test1 { @@ -55,3 +55,9 @@ namespace test10 { void test() { foo(); } inline void foo() __attribute__((gnu_inline)); } + +namespace test11 { + inline void foo() __attribute__((dllexport)); + inline void bar() __attribute__((dllimport)); + void test() { foo(); bar(); } +} diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp index 1b76a86dcb5ac..f32036a025f4c 100644 --- a/test/SemaCXX/undefined-internal.cpp +++ b/test/SemaCXX/undefined-internal.cpp @@ -15,9 +15,9 @@ namespace test1 { namespace test2 { namespace { - void foo(); // expected-warning {{function 'test2::<anonymous namespace>::foo' has internal linkage but is not defined}} - extern int var; // expected-warning {{variable 'test2::<anonymous namespace>::var' has internal linkage but is not defined}} - template <class T> void bar(); // expected-warning {{function 'test2::<anonymous namespace>::bar<int>' has internal linkage but is not defined}} + void foo(); // expected-warning {{function 'test2::(anonymous namespace)::foo' has internal linkage but is not defined}} + extern int var; // expected-warning {{variable 'test2::(anonymous namespace)::var' has internal linkage but is not defined}} + template <class T> void bar(); // expected-warning {{function 'test2::(anonymous namespace)::bar<int>' has internal linkage but is not defined}} } void test() { foo(); // expected-note {{used here}} @@ -49,11 +49,11 @@ namespace test3 { namespace test4 { namespace { struct A { - A(); // expected-warning {{function 'test4::<anonymous namespace>::A::A' has internal linkage but is not defined}} - ~A();// expected-warning {{function 'test4::<anonymous namespace>::A::~A' has internal linkage but is not defined}} - virtual void foo(); // expected-warning {{function 'test4::<anonymous namespace>::A::foo' has internal linkage but is not defined}} + A(); // expected-warning {{function 'test4::(anonymous namespace)::A::A' has internal linkage but is not defined}} + ~A();// expected-warning {{function 'test4::(anonymous namespace)::A::~A' has internal linkage but is not defined}} + virtual void foo(); // expected-warning {{function 'test4::(anonymous namespace)::A::foo' has internal linkage but is not defined}} virtual void bar() = 0; - virtual void baz(); // expected-warning {{function 'test4::<anonymous namespace>::A::baz' has internal linkage but is not defined}} + virtual void baz(); // expected-warning {{function 'test4::(anonymous namespace)::A::baz' has internal linkage but is not defined}} }; } @@ -75,8 +75,8 @@ namespace test5 { } template <class N> struct B { - static int var; // expected-warning {{variable 'test5::B<test5::<anonymous>::A>::var' has internal linkage but is not defined}} - static void foo(); // expected-warning {{function 'test5::B<test5::<anonymous>::A>::foo' has internal linkage but is not defined}} + static int var; // expected-warning {{variable 'test5::B<test5::(anonymous namespace)::A>::var' has internal linkage but is not defined}} + static void foo(); // expected-warning {{function 'test5::B<test5::(anonymous namespace)::A>::foo' has internal linkage but is not defined}} }; void test() { @@ -175,7 +175,7 @@ namespace cxx11_odr_rules { namespace OverloadUse { namespace { void f(); - void f(int); // expected-warning {{function 'OverloadUse::<anonymous namespace>::f' has internal linkage but is not defined}} + void f(int); // expected-warning {{function 'OverloadUse::(anonymous namespace)::f' has internal linkage but is not defined}} } template<void x()> void t(int*) { x(); } template<void x(int)> void t(long*) { x(10); } // expected-note {{used here}} @@ -193,7 +193,7 @@ namespace test7 { namespace test8 { typedef struct { - void bar(); // expected-warning {{function 'test8::<anonymous struct>::bar' has internal linkage but is not defined}} + void bar(); // expected-warning {{function 'test8::(anonymous struct)::bar' has internal linkage but is not defined}} void foo() { bar(); // expected-note {{used here}} } @@ -204,7 +204,7 @@ namespace test9 { namespace { struct X { virtual void notused() = 0; - virtual void used() = 0; // expected-warning {{function 'test9::<anonymous namespace>::X::used' has internal linkage but is not defined}} + virtual void used() = 0; // expected-warning {{function 'test9::(anonymous namespace)::X::used' has internal linkage but is not defined}} }; } void test(X &x) { @@ -217,7 +217,7 @@ namespace test10 { namespace { struct X { virtual void notused() = 0; - virtual void used() = 0; // expected-warning {{function 'test10::<anonymous namespace>::X::used' has internal linkage but is not defined}} + virtual void used() = 0; // expected-warning {{function 'test10::(anonymous namespace)::X::used' has internal linkage but is not defined}} void test() { notused(); @@ -244,11 +244,11 @@ namespace test11 { }; struct B { - bool operator()() const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator()' has internal linkage but is not defined}} - void operator!() const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator!' has internal linkage but is not defined}} - bool operator+(const B&) const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator+' has internal linkage but is not defined}} - int operator[](int) const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator[]' has internal linkage but is not defined}} - const B* operator->() const; // expected-warning {{function 'test11::<anonymous namespace>::B::operator->' has internal linkage but is not defined}} + bool operator()() const; // expected-warning {{function 'test11::(anonymous namespace)::B::operator()' has internal linkage but is not defined}} + void operator!() const; // expected-warning {{function 'test11::(anonymous namespace)::B::operator!' has internal linkage but is not defined}} + bool operator+(const B&) const; // expected-warning {{function 'test11::(anonymous namespace)::B::operator+' has internal linkage but is not defined}} + int operator[](int) const; // expected-warning {{function 'test11::(anonymous namespace)::B::operator[]' has internal linkage but is not defined}} + const B* operator->() const; // expected-warning {{function 'test11::(anonymous namespace)::B::operator->' has internal linkage but is not defined}} int member; }; } @@ -278,18 +278,18 @@ namespace test12 { struct Cls { virtual void f(int) = 0; virtual void f(int, double) = 0; - void g(int); // expected-warning {{function 'test12::<anonymous namespace>::Cls::g' has internal linkage but is not defined}} + void g(int); // expected-warning {{function 'test12::(anonymous namespace)::Cls::g' has internal linkage but is not defined}} void g(int, double); virtual operator T1() = 0; virtual operator T2() = 0; virtual operator T3&() = 0; - operator T4(); // expected-warning {{function 'test12::<anonymous namespace>::Cls::operator T4' has internal linkage but is not defined}} - operator T5(); // expected-warning {{function 'test12::<anonymous namespace>::Cls::operator T5' has internal linkage but is not defined}} - operator T6&(); // expected-warning {{function 'test12::<anonymous namespace>::Cls::operator class test12::T6 &' has internal linkage but is not defined}} + operator T4(); // expected-warning {{function 'test12::(anonymous namespace)::Cls::operator T4' has internal linkage but is not defined}} + operator T5(); // expected-warning {{function 'test12::(anonymous namespace)::Cls::operator T5' has internal linkage but is not defined}} + operator T6&(); // expected-warning {{function 'test12::(anonymous namespace)::Cls::operator test12::T6 &' has internal linkage but is not defined}} }; struct Cls2 { - Cls2(T7); // expected-warning {{function 'test12::<anonymous namespace>::Cls2::Cls2' has internal linkage but is not defined}} + Cls2(T7); // expected-warning {{function 'test12::(anonymous namespace)::Cls2::Cls2' has internal linkage but is not defined}} }; } diff --git a/test/SemaCXX/underlying_type.cpp b/test/SemaCXX/underlying_type.cpp index 7bca06bf074e5..2a972b174e86f 100644 --- a/test/SemaCXX/underlying_type.cpp +++ b/test/SemaCXX/underlying_type.cpp @@ -41,3 +41,17 @@ enum class foo : uint { bar }; static_assert(is_same_type<underlying_type<foo>::type, unsigned>::value, "foo has the wrong underlying type"); + +namespace PR19966 { + void PR19966(enum Invalid) { // expected-note 2{{forward declaration of}} + // expected-error@-1 {{ISO C++ forbids forward references to 'enum'}} + // expected-error@-2 {{variable has incomplete type}} + __underlying_type(Invalid) dont_crash; + // expected-error@-1 {{cannot determine underlying type of incomplete enumeration type 'PR19966::Invalid'}} + } + enum E { // expected-note {{forward declaration of 'E'}} + a = (__underlying_type(E)){} + // expected-error@-1 {{cannot determine underlying type of incomplete enumeration type 'PR19966::E'}} + // expected-error@-2 {{constant expression}} + }; +} diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index 687bfd2638d4f..4dcd34858abbf 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fcxx-exceptions %s -verify +// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fcxx-exceptions %s -verify -std=c++1y // Stub out types for 'typeid' to work. namespace std { class type_info {}; } @@ -147,3 +147,6 @@ int test_const_ref() { consume_const_ref(n); return n; // expected-warning {{uninitialized when used here}} } + +// Don't crash here. +auto PR19996 = [a=0]{int t; return a;}; diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 4991ebee8b311..677a141f3ec35 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -117,7 +117,7 @@ void setupA(bool x) { A a20{a20}; // expected-warning {{variable 'a20' is uninitialized when used within its own initialization}} A a21 = {a21}; // expected-warning {{variable 'a21' is uninitialized when used within its own initialization}} - // FIXME: Make the local uninitialized warning consistant with the global + // FIXME: Make the local uninitialized warning consistent with the global // uninitialized checking. A *a22 = new A(a22->count); // expected-warning {{variable 'a22' is uninitialized when used within its own initialization}} A *a23 = new A(a23->ONE); // expected-warning {{variable 'a23' is uninitialized when used within its own initialization}} diff --git a/test/SemaCXX/unreachable-code.cpp b/test/SemaCXX/unreachable-code.cpp index 743290e1b9e55..fd006c099e7dc 100644 --- a/test/SemaCXX/unreachable-code.cpp +++ b/test/SemaCXX/unreachable-code.cpp @@ -1,17 +1,29 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -Wunreachable-code -fblocks -verify %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -Wunreachable-code-aggressive -fblocks -verify %s int j; -void bar() { } +int bar(); int test1() { for (int i = 0; i != 10; - ++i) { // expected-warning {{will never be executed}} + ++i) { // expected-warning {{loop will run at most once (loop increment never executed)}} if (j == 23) // missing {}'s bar(); return 1; } return 0; - return 1; // expected-warning {{will never be executed}} + return 1; // expected-warning {{will never be executed}} +} + +int test1_B() { + for (int i = 0; + i != 10; + ++i) { // expected-warning {{loop will run at most once (loop increment never executed)}} + if (j == 23) // missing {}'s + bar(); + return 1; + } + return 0; + return bar(); // expected-warning {{will never be executed}} } void test2(int i) { diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp index 24d92f175c302..40f80a70ef371 100644 --- a/test/SemaCXX/using-decl-1.cpp +++ b/test/SemaCXX/using-decl-1.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s extern "C" { void f(bool); } @@ -160,3 +161,97 @@ namespace M { } } using N::M::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_nested_specifier::N::M'; did you mean 'N::FFF'?}} } + +namespace UsingDeclVsHiddenName { + namespace A { + enum HiddenTag1 {}; // expected-note {{previous use is here}} + enum HiddenTag2 {}; // expected-note {{target}} + int HiddenFn1; // expected-note {{target}} + int HiddenFn2; // expected-note {{target}} + int HiddenLocalExtern1; + int HiddenLocalExtern2; + } + + namespace B { + using A::HiddenTag1; + using A::HiddenFn1; // expected-note {{using declaration}} + using A::HiddenLocalExtern1; + + struct S { + friend struct HiddenTag1; // expected-error {{tag type that does not match previous}} + friend struct HiddenTag2; // expected-note {{conflicting declaration}} + friend void HiddenFn1(); // expected-error {{cannot befriend target of using declaration}} + friend void HiddenFn2(); // expected-note {{conflicting declaration}} + void f() { + // OK, these are not in the scope of namespace B, even though they're + // members of the namespace. + void HiddenLocalExtern1(); + void HiddenLocalExtern2(); + } + }; + + using A::HiddenTag2; // expected-error {{conflicts with declaration already in scope}} + using A::HiddenFn2; // expected-error {{conflicts with declaration already in scope}} + using A::HiddenLocalExtern2; + } +} + +namespace PR19171 { + struct Z { + Z(); + }; + + typedef struct { + Z i; + } S; + + struct Y : S { + using S::S; +#if __cplusplus < 201103L + // expected-error@-2 {{no member named 'S' in 'PR19171::S'}} +#endif + }; + + // [namespace.udecl]p3: In a using-declaration used as a member-declaration, + // the nested-name-specifier shall name a base class of the class being defined. + // If such a using-declaration names a constructor, the nested-name-specifier + // shall name a direct base class of the class being defined; + + struct B_blah { }; + struct C_blah : B_blah { C_blah(int); }; // expected-note 0-1{{declared here}} + struct D1 : C_blah { + // FIXME: We should be able to correct this in C++11 mode. + using B_blah::C_blah; // expected-error-re {{no member named 'C_blah' in 'PR19171::B_blah'{{$}}}} + }; + struct D2 : C_blah { + // Somewhat bizarrely, this names the injected-class-name of B_blah within + // C_blah, and is valid. + using C_blah::B_blah; + }; + struct D3 : C_blah { + using C_blah::D_blah; +#if __cplusplus < 201103L + // expected-error-re@-2 {{no member named 'D_blah' in 'PR19171::C_blah'{{$}}}} +#else + // expected-error@-4 {{no member named 'D_blah' in 'PR19171::C_blah'; did you mean 'C_blah'?}} +#endif + }; +#if __cplusplus >= 201103L + D3 d3(0); // ok +#endif + + struct E { }; + struct EE { int EE; }; + struct F : E { + using E::EE; // expected-error-re {{no member named 'EE' in 'PR19171::E'{{$}}}} + }; +} + +namespace TypoCorrectTemplateMember { + struct A { + template<typename T> void foobar(T); // expected-note {{'foobar' declared here}} + }; + struct B : A { + using A::goobar; // expected-error {{no member named 'goobar' in 'TypoCorrectTemplateMember::A'; did you mean 'foobar'?}} + }; +} diff --git a/test/SemaCXX/vararg-class.cpp b/test/SemaCXX/vararg-class.cpp new file mode 100644 index 0000000000000..08f521cbd539b --- /dev/null +++ b/test/SemaCXX/vararg-class.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -verify -Wclass-varargs -std=c++98 %s +// RUN: %clang_cc1 -verify -Wclass-varargs -std=c++11 %s + +struct A {}; +struct B { ~B(); }; +class C { char *c_str(); }; +struct D { char *c_str(); }; +struct E { E(); }; +struct F { F(); char *c_str(); }; + +void v(...); +void w(const char*, ...) __attribute__((format(printf, 1, 2))); + +void test(A a, B b, C c, D d, E e, F f) { + v(a); // expected-warning-re {{passing object of class type 'A' through variadic function{{$}}}} + v(b); // expected-error-re {{cannot pass object of non-{{POD|trivial}} type 'B' through variadic function; call will abort at runtime}} + v(c); // expected-warning {{passing object of class type 'C' through variadic function; did you mean to call '.c_str()'?}} + v(d); // expected-warning {{passing object of class type 'D' through variadic function; did you mean to call '.c_str()'?}} + v(e); + v(f); +#if __cplusplus < 201103L + // expected-error@-3 {{cannot pass object of non-POD type 'E' through variadic function; call will abort at runtime}} + // expected-error@-3 {{cannot pass object of non-POD type 'F' through variadic function; call will abort at runtime}} +#else + // expected-warning-re@-6 {{passing object of class type 'E' through variadic function{{$}}}} + // expected-warning@-6 {{passing object of class type 'F' through variadic function; did you mean to call '.c_str()'?}} +#endif + + v(d.c_str()); + v(f.c_str()); + v(0); + v('x'); + + w("%s", a); // expected-warning {{format specifies type 'char *' but the argument has type 'A'}} + w("%s", b); // expected-error-re {{cannot pass non-{{POD|trivial}} object of type 'B' to variadic function; expected type from format string was 'char *'}} + w("%s", c); // expected-warning {{format specifies type 'char *' but the argument has type 'C'}} + w("%s", d); // expected-warning {{format specifies type 'char *' but the argument has type 'D'}} + w("%s", e); + w("%s", f); +#if __cplusplus < 201103L + // expected-error@-3 {{cannot pass non-POD object of type 'E' to variadic function; expected type from format string was 'char *'}} + // expected-error@-3 {{cannot pass non-POD object of type 'F' to variadic function; expected type from format string was 'char *'}} + // expected-note@-4 {{did you mean to call the c_str() method?}} +#else + // expected-warning@-7 {{format specifies type 'char *' but the argument has type 'E'}} + // expected-warning@-7 {{format specifies type 'char *' but the argument has type 'F'}} +#endif +} diff --git a/test/SemaCXX/vector-casts.cpp b/test/SemaCXX/vector-casts.cpp index 681a07ea4707d..2ccd5979c7f7b 100644 --- a/test/SemaCXX/vector-casts.cpp +++ b/test/SemaCXX/vector-casts.cpp @@ -2,6 +2,7 @@ typedef int __v2si __attribute__((__vector_size__(8))); typedef short __v4hi __attribute__((__vector_size__(8))); typedef short __v8hi __attribute__((__vector_size__(16))); +typedef short __v3hi __attribute__((__ext_vector_type__(3))); struct S { }; // expected-note 2 {{candidate constructor}} @@ -22,19 +23,43 @@ void f() { (void)reinterpret_cast<__v2si>(ll); (void)(__v2si)(ll); - (void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' to 'S' is not allowed}} - (void)(S)v2si; // expected-error {{no matching conversion for C-style cast from '__v2si' to 'S'}} - (void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'S' to '__v2si' is not allowed}} - (void)(__v2si)s; // expected-error {{cannot convert 'S' to '__v2si' without a conversion operator}} + (void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' (vector of 2 'int' values) to 'S' is not allowed}} + (void)(S)v2si; // expected-error {{no matching conversion for C-style cast from '__v2si' (vector of 2 'int' values) to 'S'}} + (void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'S' to '__v2si' (vector of 2 'int' values) is not allowed}} + (void)(__v2si)s; // expected-error {{cannot convert 'S' to '__v2si' (vector of 2 'int' values) without a conversion operator}} - (void)reinterpret_cast<unsigned char>(v2si); // expected-error {{reinterpret_cast from vector '__v2si' to scalar 'unsigned char' of different size}} - (void)(unsigned char)v2si; // expected-error {{C-style cast from vector '__v2si' to scalar 'unsigned char' of different size}} - (void)reinterpret_cast<__v2si>(c); // expected-error {{reinterpret_cast from scalar 'unsigned char' to vector '__v2si' of different size}} + (void)reinterpret_cast<unsigned char>(v2si); // expected-error {{reinterpret_cast from vector '__v2si' (vector of 2 'int' values) to scalar 'unsigned char' of different size}} + (void)(unsigned char)v2si; // expected-error {{C-style cast from vector '__v2si' (vector of 2 'int' values) to scalar 'unsigned char' of different size}} + (void)reinterpret_cast<__v2si>(c); // expected-error {{reinterpret_cast from scalar 'unsigned char' to vector '__v2si' (vector of 2 'int' values) of different size}} - (void)reinterpret_cast<__v8hi>(v4hi); // expected-error {{reinterpret_cast from vector '__v4hi' to vector '__v8hi' of different size}} - (void)(__v8hi)v4hi; // expected-error {{C-style cast from vector '__v4hi' to vector '__v8hi' of different size}} - (void)reinterpret_cast<__v4hi>(v8hi); // expected-error {{reinterpret_cast from vector '__v8hi' to vector '__v4hi' of different size}} - (void)(__v4hi)v8hi; // expected-error {{C-style cast from vector '__v8hi' to vector '__v4hi' of different size}} + (void)reinterpret_cast<__v8hi>(v4hi); // expected-error {{reinterpret_cast from vector '__v4hi' (vector of 4 'short' values) to vector '__v8hi' (vector of 8 'short' values) of different size}} + (void)(__v8hi)v4hi; // expected-error {{C-style cast from vector '__v4hi' (vector of 4 'short' values) to vector '__v8hi' (vector of 8 'short' values) of different size}} + (void)reinterpret_cast<__v4hi>(v8hi); // expected-error {{reinterpret_cast from vector '__v8hi' (vector of 8 'short' values) to vector '__v4hi' (vector of 4 'short' values) of different size}} + (void)(__v4hi)v8hi; // expected-error {{C-style cast from vector '__v8hi' (vector of 8 'short' values) to vector '__v4hi' (vector of 4 'short' values) of different size}} } +struct testvec { + __v2si v; + void madd(const testvec& rhs) { + v = v + rhs; // expected-error {{can't convert between vector and non-scalar values}} + } + void madd2(testvec rhs) { + v = v + rhs; // expected-error {{can't convert between vector and non-scalar values}} + } +}; +// rdar://15931426 +// Conversions for return values. +__v4hi threeToFour(__v3hi v) { // expected-note {{not viable}} + return v; // expected-error {{cannot initialize return object}} +} +__v3hi fourToThree(__v4hi v) { // expected-note {{not viable}} + return v; // expected-error {{cannot initialize return object}} +} +// Conversions for calls. +void call3to4(__v4hi v) { + (void) threeToFour(v); // expected-error {{no matching function for call}} +} +void call4to3(__v3hi v) { + (void) fourToThree(v); // expected-error {{no matching function for call}} +} diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 7957c23e3e240..bcd7fedb4df2c 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -24,8 +24,8 @@ void f1_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { f1(ll16e); // expected-error{{call to 'f1' is ambiguous}} } -void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' to 'char16_e' for 1st argument}} \ - // expected-note{{candidate function not viable: no known conversion from 'convertible_to<longlong16_e>' to 'char16_e' for 1st argument}} +void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' (vector of 2 'long long' values) to 'char16_e' (vector of 16 'char' values) for 1st argument}} \ + // expected-note{{candidate function not viable: no known conversion from 'convertible_to<longlong16_e>' to 'char16_e' (vector of 16 'char' values) for 1st argument}} void f2_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { f2(c16); @@ -85,7 +85,7 @@ void casts(longlong16 ll16, longlong16_e ll16e) { (void)static_cast<longlong16>(ll16); (void)static_cast<longlong16_e>(ll16); (void)static_cast<char16>(ll16e); - (void)static_cast<char16_e>(ll16e); // expected-error{{static_cast from 'longlong16_e' to 'char16_e' is not allowed}} + (void)static_cast<char16_e>(ll16e); // expected-error{{static_cast from 'longlong16_e' (vector of 2 'long long' values) to 'char16_e' (vector of 16 'char' values) is not allowed}} (void)static_cast<longlong16>(ll16e); (void)static_cast<longlong16_e>(ll16e); @@ -194,11 +194,11 @@ typedef float fltx4 __attribute__((__vector_size__(16))); typedef double dblx2 __attribute__((__vector_size__(16))); typedef double dblx4 __attribute__((__vector_size__(32))); -void accept_fltx2(fltx2); // expected-note{{candidate function not viable: no known conversion from 'double' to 'fltx2' for 1st argument}} +void accept_fltx2(fltx2); // expected-note{{candidate function not viable: no known conversion from 'double' to 'fltx2' (vector of 2 'float' values) for 1st argument}} void accept_fltx4(fltx4); void accept_dblx2(dblx2); void accept_dblx4(dblx4); -void accept_bool(bool); // expected-note{{candidate function not viable: no known conversion from 'fltx2' to 'bool' for 1st argument}} +void accept_bool(bool); // expected-note{{candidate function not viable: no known conversion from 'fltx2' (vector of 2 'float' values) to 'bool' for 1st argument}} void test(fltx2 fltx2_val, fltx4 fltx4_val, dblx2 dblx2_val, dblx4 dblx4_val) { // Exact matches diff --git a/test/SemaCXX/virtual-base-used.cpp b/test/SemaCXX/virtual-base-used.cpp index 04518ce4d47b5..c46cf5a8c9ef7 100644 --- a/test/SemaCXX/virtual-base-used.cpp +++ b/test/SemaCXX/virtual-base-used.cpp @@ -1,42 +1,89 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify %s // PR7800 +// The Microsoft ABI doesn't have the concept of key functions, so we have different +// expectations about when functions are first required for that case. + +#ifdef MSABI +// expected-note@+2 3 {{declared private here}} +#endif class NoDestroy { ~NoDestroy(); }; // expected-note 3 {{declared private here}} struct A { virtual ~A(); }; +#ifdef MSABI +// expected-error@+3 {{field of type 'NoDestroy' has private destructor}} +#endif struct B : public virtual A { NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} }; +#ifdef MSABI +// expected-note@+3 {{implicit default constructor for 'B' first required here}} +// expected-note@+2 {{implicit destructor for 'B' first required here}} +#endif struct D : public virtual B { virtual void foo(); ~D(); }; +#ifdef MSABI +D d; // expected-note {{implicit default constructor for 'D' first required here}} +#else void D::foo() { // expected-note {{implicit destructor for 'B' first required here}} } +#endif +#ifdef MSABI +// expected-error@+3 {{field of type 'NoDestroy' has private destructor}} +#endif struct E : public virtual A { NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} }; +#ifdef MSABI +// expected-note@+2 {{implicit default constructor for 'E' first required here}} +#endif struct F : public E { // expected-note {{implicit destructor for 'E' first required here}} }; +#ifdef MSABI +// expected-note@+2 {{implicit default constructor for 'F' first required here}} +#endif struct G : public virtual F { virtual void foo(); ~G(); }; +#ifdef MSABI +G g; // expected-note {{implicit default constructor for 'G' first required here}} +#else void G::foo() { // expected-note {{implicit destructor for 'F' first required here}} } +#endif +#ifdef MSABI +// expected-note@+3 {{'H' declared here}} +// expected-error@+3 {{field of type 'NoDestroy' has private destructor}} +#endif struct H : public virtual A { NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} }; +#ifdef MSABI +// expected-error@+3 {{implicit default constructor for 'I' must explicitly initialize the base class 'H' which does not have a default constructor}} +// expected-note@+2 {{implicit destructor for 'H' first required here}} +#endif struct I : public virtual H { ~I(); }; +#ifdef MSABI +// expected-note@+3 {{implicit default constructor for 'H' first required here}} +// expected-note@+2 {{implicit default constructor for 'I' first required here}} +#endif struct J : public I { virtual void foo(); ~J(); }; +#ifdef MSABI +J j; // expected-note {{implicit default constructor for 'J' first required here}} +#else void J::foo() { // expected-note {{implicit destructor for 'H' first required here}} } +#endif diff --git a/test/SemaCXX/virtual-override-x86.cpp b/test/SemaCXX/virtual-override-x86.cpp index 75d8af3b3ea34..1d9d1fbe53b6b 100644 --- a/test/SemaCXX/virtual-override-x86.cpp +++ b/test/SemaCXX/virtual-override-x86.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple=i686-pc-unknown -fsyntax-only -verify %s -std=c++11 -cxx-abi microsoft +// RUN: %clang_cc1 -triple=i686-pc-win32 -fsyntax-only -verify %s -std=c++11 namespace PR14339 { class A { diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp index b477438ee9883..e95acabad2b1c 100644 --- a/test/SemaCXX/virtual-override.cpp +++ b/test/SemaCXX/virtual-override.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -verify %s -std=c++11 namespace T1 { class A { diff --git a/test/SemaCXX/vla.cpp b/test/SemaCXX/vla.cpp index d63b6335f4533..dae6450553aa3 100644 --- a/test/SemaCXX/vla.cpp +++ b/test/SemaCXX/vla.cpp @@ -3,3 +3,17 @@ // PR11925 int n; int (&f())[n]; // expected-error {{function declaration cannot have variably modified type}} + +namespace PR18581 { + template<typename T> struct pod {}; + template<typename T> struct error { + typename T::error e; // expected-error {{cannot be used prior to '::'}} + }; + struct incomplete; // expected-note {{forward declaration}} + + void f(int n) { + pod<int> a[n]; + error<int> b[n]; // expected-note {{instantiation}} + incomplete c[n]; // expected-error {{incomplete}} + } +} diff --git a/test/SemaCXX/vtordisp-mode.cpp b/test/SemaCXX/vtordisp-mode.cpp new file mode 100644 index 0000000000000..dc91534d26b7b --- /dev/null +++ b/test/SemaCXX/vtordisp-mode.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -std=c++11 -vtordisp-mode=0 -DVTORDISP_MODE=0 %s -verify +// RUN: %clang_cc1 -triple i686-pc-win32 -std=c++11 -vtordisp-mode=1 -DVTORDISP_MODE=1 %s -verify +// RUN: %clang_cc1 -triple i686-pc-win32 -std=c++11 -vtordisp-mode=2 -DVTORDISP_MODE=2 %s -verify + +// expected-no-diagnostics + +struct A { + A(); + virtual void foo(); +}; + +// At /vd1, there is a vtordisp before A. +struct B : virtual A { + B(); + virtual void foo(); + virtual void bar(); +}; + +// At /vd2, there is a vtordisp before B, but only because it has its own +// vftable. +struct C : virtual B { + C(); +}; + +// There are two vfptrs, two vbptrs, and some number of vtordisps. +static_assert(sizeof(C) == 2 * 4 + 2 * 4 + 4 * VTORDISP_MODE, "size mismatch"); diff --git a/test/SemaCXX/warn-absolute-value-header.cpp b/test/SemaCXX/warn-absolute-value-header.cpp new file mode 100644 index 0000000000000..925be38ace087 --- /dev/null +++ b/test/SemaCXX/warn-absolute-value-header.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -verify %s -Wabsolute-value +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only %s -Wabsolute-value -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s + +extern "C" { + int abs(int); + float fabsf(float); +} + +namespace std { + int abs(int); + float abs(float); +} + +void test(long long ll, double d, int i, float f) { + // Suggest including cmath + (void)abs(d); + // expected-warning@-1{{using integer absolute value function 'abs' when argument is of floating point type}} + // expected-note@-2{{use function 'std::abs' instead}} + // expected-note@-3{{include the header <cmath> or explicitly provide a declaration for 'std::abs'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:9-[[@LINE-4]]:12}:"std::abs" + + (void)fabsf(d); + // expected-warning@-1{{absolute value function 'fabsf' given an argument of type 'double' but has parameter of type 'float' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // expected-note@-3{{include the header <cmath> or explicitly provide a declaration for 'std::abs'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:9-[[@LINE-4]]:14}:"std::abs" + + // Suggest including cstdlib + (void)abs(ll); + // expected-warning@-1{{absolute value function 'abs' given an argument of type 'long long' but has parameter of type 'int' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // expected-note@-3{{include the header <cstdlib> or explicitly provide a declaration for 'std::abs'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:9-[[@LINE-4]]:12}:"std::abs" + (void)fabsf(ll); + // expected-warning@-1{{using floating point absolute value function 'fabsf' when argument is of integer type}} + // expected-note@-2{{use function 'std::abs' instead}} + // expected-note@-3{{include the header <cstdlib> or explicitly provide a declaration for 'std::abs'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:9-[[@LINE-4]]:14}:"std::abs" + + // Proper function already called, no warnings. + (void)abs(i); + (void)fabsf(f); + + // Declarations found, suggest name change. + (void)fabsf(i); + // expected-warning@-1{{using floating point absolute value function 'fabsf' when argument is of integer type}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)abs(f); + // expected-warning@-1{{using integer absolute value function 'abs' when argument is of floating point type}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"std::abs" +} diff --git a/test/SemaCXX/warn-absolute-value.cpp b/test/SemaCXX/warn-absolute-value.cpp new file mode 100644 index 0000000000000..8a8a6fd67d343 --- /dev/null +++ b/test/SemaCXX/warn-absolute-value.cpp @@ -0,0 +1,823 @@ +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -verify %s -Wabsolute-value -std=c++11 +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only %s -Wabsolute-value -fdiagnostics-parseable-fixits -std=c++11 2>&1 | FileCheck %s + +extern "C" { +int abs(int); +long int labs(long int); +long long int llabs(long long int); + +float fabsf(float); +double fabs(double); +long double fabsl(long double); + +float cabsf(float _Complex); +double cabs(double _Complex); +long double cabsl(long double _Complex); +} + +namespace std { + +inline namespace __1 { +int abs(int); +long int abs(long int); +long long int abs(long long int); +} + +float abs(float); +double abs(double); +long double abs(long double); + +template <typename T> +double abs(T); + +} + +void test_int(int x) { + (void)std::abs(x); + + (void)abs(x); + (void)labs(x); + (void)llabs(x); + + (void)fabsf(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)fabs(x); + // expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)fabsl(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)cabsf(x); + // expected-warning@-1 {{using complex absolute value function 'cabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)cabs(x); + // expected-warning@-1 {{using complex absolute value function 'cabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)cabsl(x); + // expected-warning@-1 {{using complex absolute value function 'cabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)__builtin_abs(x); + (void)__builtin_labs(x); + (void)__builtin_llabs(x); + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_fabs(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_cabs(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" +} + +void test_long(long x) { + (void)std::abs(x); + + (void)abs(x); // no warning - int and long are same length for this target + (void)labs(x); + (void)llabs(x); + + (void)fabsf(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)fabs(x); + // expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)fabsl(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)cabsf(x); + // expected-warning@-1 {{using complex absolute value function 'cabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)cabs(x); + // expected-warning@-1 {{using complex absolute value function 'cabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)cabsl(x); + // expected-warning@-1 {{using complex absolute value function 'cabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)__builtin_abs(x); // no warning - int and long are same length for + // this target + (void)__builtin_labs(x); + (void)__builtin_llabs(x); + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_fabs(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_cabs(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" +} + +void test_long_long(long long x) { + (void)std::abs(x); + + (void)abs(x); + // expected-warning@-1{{absolute value function 'abs' given an argument of type 'long long' but has parameter of type 'int' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"std::abs" + (void)labs(x); + // expected-warning@-1{{absolute value function 'labs' given an argument of type 'long long' but has parameter of type 'long' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)llabs(x); + + (void)fabsf(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)fabs(x); + // expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)fabsl(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)cabsf(x); + // expected-warning@-1 {{using complex absolute value function 'cabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)cabs(x); + // expected-warning@-1 {{using complex absolute value function 'cabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)cabsl(x); + // expected-warning@-1 {{using complex absolute value function 'cabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)__builtin_abs(x); + // expected-warning@-1{{absolute value function '__builtin_abs' given an argument of type 'long long' but has parameter of type 'int' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"std::abs" + (void)__builtin_labs(x); + // expected-warning@-1{{absolute value function '__builtin_labs' given an argument of type 'long long' but has parameter of type 'long' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_llabs(x); + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_fabs(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsf' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_cabs(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabs' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsl' when argument is of integer type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" +} + +void test_float(float x) { + (void)std::abs(x); + + (void)abs(x); + // expected-warning@-1 {{using integer absolute value function 'abs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"std::abs" + (void)labs(x); + // expected-warning@-1 {{using integer absolute value function 'labs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)llabs(x); + // expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)fabsf(x); + (void)fabs(x); + (void)fabsl(x); + + (void)cabsf(x); + // expected-warning@-1 {{using complex absolute value function 'cabsf' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)cabs(x); + // expected-warning@-1 {{using complex absolute value function 'cabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)cabsl(x); + // expected-warning@-1 {{using complex absolute value function 'cabsl' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)__builtin_abs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"std::abs" + (void)__builtin_labs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_llabs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + + (void)__builtin_fabsf(x); + (void)__builtin_fabs(x); + (void)__builtin_fabsl(x); + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsf' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_cabs(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsl' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" +} + +void test_double(double x) { + (void)std::abs(x); + + (void)abs(x); + // expected-warning@-1 {{using integer absolute value function 'abs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"std::abs" + (void)labs(x); + // expected-warning@-1 {{using integer absolute value function 'labs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)llabs(x); + // expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)fabsf(x); + // expected-warning@-1{{absolute value function 'fabsf' given an argument of type 'double' but has parameter of type 'float' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)fabs(x); + (void)fabsl(x); + + (void)cabsf(x); + // expected-warning@-1 {{using complex absolute value function 'cabsf' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)cabs(x); + // expected-warning@-1 {{using complex absolute value function 'cabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)cabsl(x); + // expected-warning@-1 {{using complex absolute value function 'cabsl' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)__builtin_abs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"std::abs" + (void)__builtin_labs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_llabs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + + (void)__builtin_fabsf(x); + // expected-warning@-1{{absolute value function '__builtin_fabsf' given an argument of type 'double' but has parameter of type 'float' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_fabs(x); + (void)__builtin_fabsl(x); + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsf' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_cabs(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsl' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" +} + +void test_long_double(long double x) { + (void)std::abs(x); + + (void)abs(x); + // expected-warning@-1 {{using integer absolute value function 'abs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"std::abs" + (void)labs(x); + // expected-warning@-1 {{using integer absolute value function 'labs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)llabs(x); + // expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)fabsf(x); + // expected-warning@-1{{absolute value function 'fabsf' given an argument of type 'long double' but has parameter of type 'float' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)fabs(x); + // expected-warning@-1{{absolute value function 'fabs' given an argument of type 'long double' but has parameter of type 'double' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)fabsl(x); + + (void)cabsf(x); + // expected-warning@-1 {{using complex absolute value function 'cabsf' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + (void)cabs(x); + // expected-warning@-1 {{using complex absolute value function 'cabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"std::abs" + (void)cabsl(x); + // expected-warning@-1 {{using complex absolute value function 'cabsl' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"std::abs" + + (void)__builtin_abs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"std::abs" + (void)__builtin_labs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_llabs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + + (void)__builtin_fabsf(x); + // expected-warning@-1{{absolute value function '__builtin_fabsf' given an argument of type 'long double' but has parameter of type 'float' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_fabs(x); + // expected-warning@-1{{absolute value function '__builtin_fabs' given an argument of type 'long double' but has parameter of type 'double' which may cause truncation of value}} + // expected-note@-2{{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_fabsl(x); + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsf' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" + (void)__builtin_cabs(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabs' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"std::abs" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{using complex absolute value function '__builtin_cabsl' when argument is of floating point type}} + // expected-note@-2 {{use function 'std::abs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"std::abs" +} + +void test_complex_float(_Complex float x) { + (void)abs(x); + // expected-warning@-1 {{using integer absolute value function 'abs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"cabsf" + (void)labs(x); + // expected-warning@-1 {{using integer absolute value function 'labs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsf" + (void)llabs(x); + // expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsf" + + (void)fabsf(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsf" + (void)fabs(x); + // expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsf" + (void)fabsl(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsf" + + (void)cabsf(x); + (void)cabs(x); + (void)cabsl(x); + + (void)__builtin_abs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"__builtin_cabsf" + (void)__builtin_labs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsf" + (void)__builtin_llabs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsf" + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsf" + (void)__builtin_fabs(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsf" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsf' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsf" + + (void)__builtin_cabsf(x); + (void)__builtin_cabs(x); + (void)__builtin_cabsl(x); +} + +void test_complex_double(_Complex double x) { + (void)abs(x); + // expected-warning@-1 {{using integer absolute value function 'abs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"cabs" + (void)labs(x); + // expected-warning@-1 {{using integer absolute value function 'labs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabs" + (void)llabs(x); + // expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs" + + (void)fabsf(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of complex type}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs" + (void)fabs(x); + // expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabs" + (void)fabsl(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of complex type}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs" + + (void)cabsf(x); + // expected-warning@-1 {{absolute value function 'cabsf' given an argument of type '_Complex double' but has parameter of type '_Complex float' which may cause truncation of value}} + // expected-note@-2 {{use function 'cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs" + (void)cabs(x); + (void)cabsl(x); + + (void)__builtin_abs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"__builtin_cabs" + (void)__builtin_labs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabs" + (void)__builtin_llabs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs" + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs" + (void)__builtin_fabs(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabs" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{absolute value function '__builtin_cabsf' given an argument of type '_Complex double' but has parameter of type '_Complex float' which may cause truncation of value}} + // expected-note@-2 {{use function '__builtin_cabs' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs" + (void)__builtin_cabs(x); + (void)__builtin_cabsl(x); +} + +void test_complex_long_double(_Complex long double x) { + (void)abs(x); + // expected-warning@-1 {{using integer absolute value function 'abs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"cabsl" + (void)labs(x); + // expected-warning@-1 {{using integer absolute value function 'labs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsl" + (void)llabs(x); + // expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl" + + (void)fabsf(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl" + (void)fabs(x); + // expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsl" + (void)fabsl(x); + // expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of complex type}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl" + + (void)cabsf(x); + // expected-warning@-1 {{absolute value function 'cabsf' given an argument of type '_Complex long double' but has parameter of type '_Complex float' which may cause truncation of value}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl" + (void)cabs(x); + // expected-warning@-1 {{absolute value function 'cabs' given an argument of type '_Complex long double' but has parameter of type '_Complex double' which may cause truncation of value}} + // expected-note@-2 {{use function 'cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsl" + (void)cabsl(x); + + (void)__builtin_abs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"__builtin_cabsl" + (void)__builtin_labs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsl" + (void)__builtin_llabs(x); + // expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl" + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl" + (void)__builtin_fabs(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsl" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of complex type}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{absolute value function '__builtin_cabsf' given an argument of type '_Complex long double' but has parameter of type '_Complex float' which may cause truncation of value}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl" + (void)__builtin_cabs(x); + // expected-warning@-1 {{absolute value function '__builtin_cabs' given an argument of type '_Complex long double' but has parameter of type '_Complex double' which may cause truncation of value}} + // expected-note@-2 {{use function '__builtin_cabsl' instead}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsl" + (void)__builtin_cabsl(x); +} + +void test_unsigned_int(unsigned int x) { + (void)std::abs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'std::abs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:17}:"" + + (void)abs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'abs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"" + (void)labs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'labs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"" + (void)llabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'llabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + + (void)fabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'fabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + (void)fabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'fabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"" + (void)fabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'fabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + + (void)cabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'cabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + (void)cabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'cabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"" + (void)cabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to 'cabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + + (void)__builtin_abs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_abs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"" + (void)__builtin_labs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_labs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"" + (void)__builtin_llabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_llabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_fabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + (void)__builtin_fabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_fabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_fabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_cabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + (void)__builtin_cabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_cabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned int' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_cabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" +} + +void test_unsigned_long(unsigned long x) { + (void)std::abs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'std::abs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:17}:"" + + (void)abs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'abs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"" + (void)labs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'labs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"" + (void)llabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'llabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + + (void)fabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'fabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + (void)fabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'fabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"" + (void)fabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'fabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + + (void)cabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'cabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + (void)cabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'cabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"" + (void)cabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to 'cabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"" + + (void)__builtin_abs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_abs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"" + (void)__builtin_labs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_labs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"" + (void)__builtin_llabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_llabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + + (void)__builtin_fabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_fabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + (void)__builtin_fabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_fabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"" + (void)__builtin_fabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_fabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + + (void)__builtin_cabsf(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_cabsf' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" + (void)__builtin_cabs(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_cabs' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"" + (void)__builtin_cabsl(x); + // expected-warning@-1 {{taking the absolute value of unsigned type 'unsigned long' has no effect}} + // expected-note@-2 {{remove the call to '__builtin_cabsl' since unsigned values cannot be negative}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"" +} + diff --git a/test/SemaCXX/warn-address.cpp b/test/SemaCXX/warn-address.cpp new file mode 100644 index 0000000000000..219edfdc80c2e --- /dev/null +++ b/test/SemaCXX/warn-address.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-bool-conversion -Wno-string-compare -Wno-tautological-compare -Waddress %s +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void foo(); +int arr[5]; +int global; +const char* str = ""; + +void test() { + if (foo) {} // expected-warning{{always evaluate to 'true'}} \ + // expected-note{{silence}} + if (arr) {} // expected-warning{{always evaluate to 'true'}} + if (&global) {} // expected-warning{{always evaluate to 'true'}} + if (foo == 0) {} // expected-warning{{always false}} \ + // expected-note{{silence}} + if (arr == 0) {} // expected-warning{{always false}} + if (&global == 0) {} // expected-warning{{always false}} + + if (str == "foo") {} // expected-warning{{unspecified}} +} diff --git a/test/SemaCXX/warn-bad-memaccess.cpp b/test/SemaCXX/warn-bad-memaccess.cpp index 7a7459acee1d3..e86610ab64d96 100644 --- a/test/SemaCXX/warn-bad-memaccess.cpp +++ b/test/SemaCXX/warn-bad-memaccess.cpp @@ -24,6 +24,11 @@ public: struct X1 { virtual void f(); } x1; struct X2 : virtual S1 {} x2; +struct ContainsDynamic { X1 dynamic; } contains_dynamic; +struct DeepContainsDynamic { ContainsDynamic m; } deep_contains_dynamic; +struct ContainsArrayDynamic { X1 dynamic[1]; } contains_array_dynamic; +struct ContainsPointerDynamic { X1 *dynamic; } contains_pointer_dynamic; + void test_warn() { memset(&x1, 0, sizeof x1); // \ // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ @@ -33,22 +38,22 @@ void test_warn() { // expected-note {{explicitly cast the pointer to silence this warning}} memmove(&x1, 0, sizeof x1); // \ - // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \ + // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memmove(0, &x1, sizeof x1); // \ - // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be moved}} \ + // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be moved}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcpy(&x1, 0, sizeof x1); // \ - // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \ + // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcpy(0, &x1, sizeof x1); // \ - // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be copied}} \ + // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be copied}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcmp(&x1, 0, sizeof x1); // \ - // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \ + // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \ // expected-note {{explicitly cast the pointer to silence this warning}} memcmp(0, &x1, sizeof x1); // \ - // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \ + // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \ // expected-note {{explicitly cast the pointer to silence this warning}} __builtin_memset(&x1, 0, sizeof x1); // \ @@ -90,6 +95,16 @@ void test_warn() { __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); // \ // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} + + // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}} + // expected-note@+1 {{explicitly cast the pointer to silence this warning}} + memset(&contains_dynamic, 0, sizeof(contains_dynamic)); + // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}} + // expected-note@+1 {{explicitly cast the pointer to silence this warning}} + memset(&deep_contains_dynamic, 0, sizeof(deep_contains_dynamic)); + // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}} + // expected-note@+1 {{explicitly cast the pointer to silence this warning}} + memset(&contains_array_dynamic, 0, sizeof(contains_array_dynamic)); } void test_nowarn(void *void_ptr) { @@ -107,6 +122,8 @@ void test_nowarn(void *void_ptr) { memset(&s3, 0, sizeof s3); memset(&c1, 0, sizeof c1); + memset(&contains_pointer_dynamic, 0, sizeof(contains_pointer_dynamic)); + // Unevaluated code shouldn't warn. (void)sizeof memset(&x1, 0, sizeof x1); diff --git a/test/SemaCXX/warn-bool-conversion.cpp b/test/SemaCXX/warn-bool-conversion.cpp index b3d136ecf2b13..b4628947f06e8 100644 --- a/test/SemaCXX/warn-bool-conversion.cpp +++ b/test/SemaCXX/warn-bool-conversion.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +namespace BooleanFalse { int* j = false; // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} void foo(int* i, int *j=(false)) // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} @@ -22,3 +23,98 @@ double f(...); // isn't flagged. template <int N> struct S {}; S<sizeof(f(false))> s; + +} + +namespace Function { +void f1(); + +struct S { + static void f2(); +}; + +extern void f3() __attribute__((weak_import)); + +struct S2 { + static void f4() __attribute__((weak_import)); +}; + +bool f5(); +bool f6(int); + +void bar() { + bool b; + + b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} \ + expected-note {{suffix with parentheses to turn this into a function call}} + b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + + // implicit casts of weakly imported symbols are ok: + b = f3; + if (f3) {} + b = S2::f4; + if (S2::f4) {} +} +} + +namespace Array { + #define GetValue(ptr) ((ptr) ? ptr[0] : 0) + extern int a[] __attribute__((weak)); + int b[] = {8,13,21}; + struct { + int x[10]; + } c; + const char str[] = "text"; + void ignore() { + if (a) {} + if (a) {} + (void)GetValue(b); + } + void test() { + if (b) {} + // expected-warning@-1{{address of array 'b' will always evaluate to 'true'}} + if (b) {} + // expected-warning@-1{{address of array 'b' will always evaluate to 'true'}} + if (c.x) {} + // expected-warning@-1{{address of array 'c.x' will always evaluate to 'true'}} + if (str) {} + // expected-warning@-1{{address of array 'str' will always evaluate to 'true'}} + } +} + +namespace Pointer { + extern int a __attribute__((weak)); + int b; + static int c; + class S { + public: + static int a; + int b; + }; + void ignored() { + if (&a) {} + } + void test() { + S s; + if (&b) {} + // expected-warning@-1{{address of 'b' will always evaluate to 'true'}} + if (&c) {} + // expected-warning@-1{{address of 'c' will always evaluate to 'true'}} + if (&s.a) {} + // expected-warning@-1{{address of 's.a' will always evaluate to 'true'}} + if (&s.b) {} + // expected-warning@-1{{address of 's.b' will always evaluate to 'true'}} + if (&S::a) {} + // expected-warning@-1{{address of 'S::a' will always evaluate to 'true'}} + } +} diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp index 2c372c752baf4..977b862a92b50 100644 --- a/test/SemaCXX/warn-consumed-analysis.cpp +++ b/test/SemaCXX/warn-consumed-analysis.cpp @@ -51,7 +51,7 @@ public: class CONSUMABLE(unconsumed) DestructorTester { public: - DestructorTester() RETURN_TYPESTATE(unconsumed); + DestructorTester(); DestructorTester(int); void operator*() CALLABLE_WHEN("unconsumed"); @@ -82,11 +82,21 @@ ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown); void testInitialization() { ConsumableClass<int> var0; ConsumableClass<int> var1 = ConsumableClass<int>(); - - var0 = ConsumableClass<int>(); - + ConsumableClass<int> var2(42); + ConsumableClass<int> var3(var2); // copy constructor + ConsumableClass<int> var4(var0); // copy consumed value + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + *var2; + *var3; + *var4; // expected-warning {{invalid invocation of method 'operator*' on object 'var4' while it is in the 'consumed' state}} + + var0 = ConsumableClass<int>(42); + *var0; + + var0 = var1; + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} if (var0.isValid()) { *var0; @@ -98,19 +108,16 @@ void testInitialization() { } void testDestruction() { - DestructorTester D0(42), D1(42); + DestructorTester D0(42), D1(42), D2; *D0; *D1; - - DestructorTester D2; - *D2; + *D2; // expected-warning {{invalid invocation of method 'operator*' on object 'D2' while it is in the 'consumed' state}} D0.~DestructorTester(); // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} return; // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} \ - expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} \ - expected-warning {{invalid invocation of method '~DestructorTester' on object 'D2' while it is in the 'unconsumed' state}} + expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} } void testTempValue() { @@ -427,6 +434,29 @@ void testParamTypestateCaller() { testParamTypestateCallee(Var0, Var1); // expected-warning {{argument not in expected state; expected 'consumed', observed 'unconsumed'}} } + +void consumeFunc(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); +struct ParamTest { + static void consumeFuncStatic(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); + void consumeFuncMeth(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); + void operator<<(ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); +}; + +void operator>>(ParamTest& pt, ConsumableClass<int> P PARAM_TYPESTATE(unconsumed)); + + +void testFunctionParams() { + // Make sure we handle the different kinds of functions. + ConsumableClass<int> P; + + consumeFunc(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + ParamTest::consumeFuncStatic(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + ParamTest pt; + pt.consumeFuncMeth(P); // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + pt << P; // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} + pt >> P; // expected-warning {{argument not in expected state; expected 'unconsumed', observed 'consumed'}} +} + void baf3(ConsumableClass<int> var) { *var; } @@ -645,12 +675,17 @@ void read(bool sf) { } // end namespace ContinueICETest -namespace InitializerAssertionFailTest { +namespace StatusUseCaseTests { -class CONSUMABLE(unconsumed) Status { +class CONSUMABLE(unconsumed) + __attribute__((consumable_auto_cast_state)) + __attribute__((consumable_set_state_on_read)) + Status { int code; public: + static Status OK; + Status() RETURN_TYPESTATE(consumed); Status(int c) RETURN_TYPESTATE(unconsumed); @@ -660,6 +695,8 @@ public: Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed"); Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed"); + bool operator==(const Status &other) const SET_TYPESTATE(consumed); + bool check() const SET_TYPESTATE(consumed); void ignore() const SET_TYPESTATE(consumed); // Status& markAsChecked() { return *this; } @@ -667,13 +704,22 @@ public: void clear() CALLABLE_WHEN("unknown", "consumed") SET_TYPESTATE(consumed); ~Status() CALLABLE_WHEN("unknown", "consumed"); + + operator bool() const; // Will not consume the object. }; bool cond(); Status doSomething(); void handleStatus(const Status& s RETURN_TYPESTATE(consumed)); -void handleStatusPtr(const Status* s); +void handleStatusRef(Status& s); +void handleStatusPtr(Status* s); +void handleStatusUnmarked(const Status& s); + +void log(const char* msg); +void fail() __attribute__((noreturn)); +void checkStat(const Status& s); + void testSimpleTemporaries0() { doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} @@ -691,6 +737,19 @@ void testSimpleTemporaries3() { Status s = doSomething(); } // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} +void testTemporariesWithControlFlow(bool a) { + bool b = false || doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} +} + +Status testSimpleTemporariesReturn0() { + return doSomething(); +} + +Status testSimpleTemporariesReturn1() { + Status s = doSomething(); + return s; +} + void testSimpleTemporaries4() { Status s = doSomething(); s.check(); @@ -702,8 +761,17 @@ void testSimpleTemporaries5() { } void testSimpleTemporaries6() { - Status s = doSomething(); - handleStatus(s); + Status s1 = doSomething(); + handleStatus(s1); + + Status s2 = doSomething(); + handleStatusRef(s2); + + Status s3 = doSomething(); + handleStatusPtr(&s3); + + Status s4 = doSomething(); + handleStatusUnmarked(s4); } void testSimpleTemporaries7() { @@ -745,38 +813,58 @@ void testTemporariesWithConditionals3() { } void testTemporariesAndConstructors0() { - Status s(doSomething()); + Status s(doSomething()); // Test the copy constructor. s.check(); } -void testTemporariesAndConstructors1() { - // Test the copy constructor. - - Status s1 = doSomething(); +void testTemporariesAndConstructors1F() { + Status s1 = doSomething(); // Test the copy constructor. + Status s2 = s1; +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndConstructors1S() { + Status s1 = doSomething(); // Test the copy constructor. Status s2(s1); s2.check(); -} // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}} +} -void testTemporariesAndConstructors2() { +void testTemporariesAndConstructors2F() { // Test the move constructor. - Status s1 = doSomething(); - Status s2(static_cast<Status&&>(s1)); + Status s2 = static_cast<Status&&>(s1); +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndConstructors2S() { + // Test the move constructor. + Status s1 = doSomething(); + Status s2 = static_cast<Status&&>(s1); s2.check(); } -void testTemporariesAndOperators0() { +void testTemporariesAndOperators0F() { + // Test the assignment operator. + Status s1 = doSomething(); + Status s2; + s2 = s1; +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndOperators0S() { // Test the assignment operator. - Status s1 = doSomething(); Status s2; s2 = s1; s2.check(); -} // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}} +} -void testTemporariesAndOperators1() { +void testTemporariesAndOperators1F() { + // Test the move assignment operator. + Status s1 = doSomething(); + Status s2; + s2 = static_cast<Status&&>(s1); +} // expected-warning {{invalid invocation of method '~Status' on object 's2' while it is in the 'unconsumed' state}} + +void testTemporariesAndOperators1S() { // Test the move assignment operator. - Status s1 = doSomething(); Status s2; s2 = static_cast<Status&&>(s1); @@ -791,6 +879,35 @@ void testTemporariesAndOperators2() { s2.check(); } +Status testReturnAutocast() { + Status s = doSomething(); + s.check(); // consume s + return s; // should autocast back to unconsumed +} + + +namespace TestParens { + +void test3() { + checkStat((doSomething())); +} + +void test4() { + Status s = (doSomething()); + s.check(); +} + +void test5() { + (doSomething()).check(); +} + +void test6() { + if ((doSomething()) == Status::OK) + return; +} + +} // end namespace TestParens + } // end namespace InitializerAssertionFailTest @@ -820,3 +937,4 @@ namespace PR18260 { std::__1::move(x); } } // end namespace PR18260 + diff --git a/test/SemaCXX/warn-consumed-parsing.cpp b/test/SemaCXX/warn-consumed-parsing.cpp index 0a91636ea9492..5c0a04fffe36e 100644 --- a/test/SemaCXX/warn-consumed-parsing.cpp +++ b/test/SemaCXX/warn-consumed-parsing.cpp @@ -17,9 +17,9 @@ int returnTypestateForUnconsumable() { } class AttrTester0 { - void consumes() __attribute__ ((set_typestate())); // expected-error {{attribute takes one argument}} - bool testUnconsumed() __attribute__ ((test_typestate())); // expected-error {{attribute takes one argument}} - void callableWhen() __attribute__ ((callable_when())); // expected-error {{attribute takes at least 1 argument}} + void consumes() __attribute__ ((set_typestate())); // expected-error {{'set_typestate' attribute takes one argument}} + bool testUnconsumed() __attribute__ ((test_typestate())); // expected-error {{'test_typestate' attribute takes one argument}} + void callableWhen() __attribute__ ((callable_when())); // expected-error {{'callable_when' attribute takes at least 1 argument}} }; int var0 SET_TYPESTATE(consumed); // expected-warning {{'set_typestate' attribute only applies to methods}} @@ -53,3 +53,13 @@ class AttrTester2 { }; class CONSUMABLE(42) AttrTester3; // expected-error {{'consumable' attribute requires an identifier}} + + +class CONSUMABLE(unconsumed) + __attribute__((consumable_auto_cast_state)) + __attribute__((consumable_set_state_on_read)) + Status { +}; + + + diff --git a/test/SemaCXX/warn-exit-time-destructors.cpp b/test/SemaCXX/warn-exit-time-destructors.cpp index f49134b71c971..124576aa95b6d 100644 --- a/test/SemaCXX/warn-exit-time-destructors.cpp +++ b/test/SemaCXX/warn-exit-time-destructors.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wexit-time-destructors %s -verify +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wexit-time-destructors %s -verify namespace test1 { struct A { ~A(); }; @@ -23,5 +23,23 @@ void f() { static A &e = b[5]; static A &f = c[5][7]; } +} + +namespace test3 { + struct A { ~A() = default; }; + A a; + + struct B { ~B(); }; + struct C : B { ~C() = default; }; + C c; // expected-warning {{exit-time destructor}} + class D { + friend struct E; + ~D() = default; + }; + struct E : D { + D d; + ~E() = default; + }; + E e; } diff --git a/test/SemaCXX/warn-float-conversion.cpp b/test/SemaCXX/warn-float-conversion.cpp new file mode 100644 index 0000000000000..22c33040b26b8 --- /dev/null +++ b/test/SemaCXX/warn-float-conversion.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s -Wfloat-conversion + +bool ReturnBool(float f) { + return f; //expected-warning{{conversion}} +} + +char ReturnChar(float f) { + return f; //expected-warning{{conversion}} +} + +int ReturnInt(float f) { + return f; //expected-warning{{conversion}} +} + +long ReturnLong(float f) { + return f; //expected-warning{{conversion}} +} + +void Convert(float f, double d, long double ld) { + bool b; + char c; + int i; + long l; + + b = f; //expected-warning{{conversion}} + b = d; //expected-warning{{conversion}} + b = ld; //expected-warning{{conversion}} + c = f; //expected-warning{{conversion}} + c = d; //expected-warning{{conversion}} + c = ld; //expected-warning{{conversion}} + i = f; //expected-warning{{conversion}} + i = d; //expected-warning{{conversion}} + i = ld; //expected-warning{{conversion}} + l = f; //expected-warning{{conversion}} + l = d; //expected-warning{{conversion}} + l = ld; //expected-warning{{conversion}} +} + diff --git a/test/SemaCXX/warn-func-as-bool.cpp b/test/SemaCXX/warn-func-as-bool.cpp deleted file mode 100644 index b5df744f93067..0000000000000 --- a/test/SemaCXX/warn-func-as-bool.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// RUN: %clang_cc1 -x c++ -verify -fsyntax-only %s - -void f1(); - -struct S { - static void f2(); -}; - -extern void f3() __attribute__((weak_import)); - -struct S2 { - static void f4() __attribute__((weak_import)); -}; - -bool f5(); -bool f6(int); - -void bar() { - bool b; - - b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ - expected-note {{prefix with the address-of operator to silence this warning}} - if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ - expected-note {{prefix with the address-of operator to silence this warning}} - b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ - expected-note {{prefix with the address-of operator to silence this warning}} - if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ - expected-note {{prefix with the address-of operator to silence this warning}} - b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \ - expected-note {{prefix with the address-of operator to silence this warning}} \ - expected-note {{suffix with parentheses to turn this into a function call}} - b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \ - expected-note {{prefix with the address-of operator to silence this warning}} - - // implicit casts of weakly imported symbols are ok: - b = f3; - if (f3) {} - b = S2::f4; - if (S2::f4) {} -} diff --git a/test/SemaCXX/warn-global-constructors.cpp b/test/SemaCXX/warn-global-constructors.cpp index f57f0de70812a..90d8558666c3b 100644 --- a/test/SemaCXX/warn-global-constructors.cpp +++ b/test/SemaCXX/warn-global-constructors.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wglobal-constructors %s -verify +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wglobal-constructors %s -verify int opaque_int(); @@ -101,3 +101,22 @@ namespace referencemember { int a; A b = { a }; } + +namespace pr19253 { + struct A { ~A() = default; }; + A a; + + struct B { ~B(); }; + struct C : B { ~C() = default; }; + C c; // expected-warning {{global destructor}} + + class D { + friend struct E; + ~D() = default; + }; + struct E : D { + D d; + ~E() = default; + }; + E e; +} diff --git a/test/SemaCXX/warn-infinite-recursion.cpp b/test/SemaCXX/warn-infinite-recursion.cpp new file mode 100644 index 0000000000000..e1b7c5412e1f0 --- /dev/null +++ b/test/SemaCXX/warn-infinite-recursion.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion + +void a() { // expected-warning{{call itself}} + a(); +} + +void b(int x) { // expected-warning{{call itself}} + if (x) + b(x); + else + b(x+1); +} + +void c(int x) { + if (x) + c(5); +} + +void d(int x) { // expected-warning{{call itself}} + if (x) + ++x; + return d(x); +} + +// Doesn't warn on mutually recursive functions +void e(); +void f(); + +void e() { f(); } +void f() { e(); } + +// Don't warn on infinite loops +void g() { + while (true) + g(); + + g(); +} + +void h(int x) { + while (x < 5) { + h(x+1); + } +} + +void i(int x) { // expected-warning{{call itself}} + while (x < 5) { + --x; + } + i(0); +} + +int j() { // expected-warning{{call itself}} + return 5 + j(); +} + +class S { + static void a(); + void b(); +}; + +void S::a() { // expected-warning{{call itself}} + return a(); +} + +void S::b() { // expected-warning{{call itself}} + int i = 0; + do { + ++i; + b(); + } while (i > 5); +} + +template<class member> +struct T { + member m; + void a() { return a(); } // expected-warning{{call itself}} + static void b() { return b(); } // expected-warning{{call itself}} +}; + +void test_T() { + T<int> foo; + foo.a(); // expected-note{{in instantiation}} + foo.b(); // expected-note{{in instantiation}} +} + +class U { + U* u; + void Fun() { // expected-warning{{call itself}} + u->Fun(); + } +}; + +// No warnings on templated functions +// sum<0>() is instantiated, does recursively call itself, but never runs. +template <int value> +int sum() { + return value + sum<value/2>(); +} + +template<> +int sum<1>() { return 1; } + +template<int x, int y> +int calculate_value() { + if (x != y) + return sum<x - y>(); // This instantiates sum<0>() even if never called. + else + return 0; +} + +int value = calculate_value<1,1>(); + +void DoSomethingHere(); + +// DoStuff<0,0>() is instantiated, but never called. +template<int First, int Last> +int DoStuff() { + if (First + 1 == Last) { + // This branch gets removed during <0, 0> instantiation in so CFG for this + // function goes straight to the else branch. + DoSomethingHere(); + } else { + DoStuff<First, (First + Last)/2>(); + DoStuff<(First + Last)/2, Last>(); + } + return 0; +} +int stuff = DoStuff<0, 1>(); + +template<int x> +struct Wrapper { + static int run() { + // Similar to the above, Wrapper<0>::run() will discard the if statement. + if (x == 1) + return 0; + return Wrapper<x/2>::run(); + } + static int run2() { // expected-warning{{call itself}} + return run2(); + } +}; + +template <int x> +int test_wrapper() { + if (x != 0) + return Wrapper<x>::run() + + Wrapper<x>::run2(); // expected-note{{instantiation}} + return 0; +} + +int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} diff --git a/test/SemaCXX/warn-memsize-comparison.cpp b/test/SemaCXX/warn-memsize-comparison.cpp new file mode 100644 index 0000000000000..54c410e3dc0b8 --- /dev/null +++ b/test/SemaCXX/warn-memsize-comparison.cpp @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// + +typedef __SIZE_TYPE__ size_t; +extern "C" void *memset(void *, int, size_t); +extern "C" void *memmove(void *s1, const void *s2, size_t n); +extern "C" void *memcpy(void *s1, const void *s2, size_t n); +extern "C" void *memcmp(void *s1, const void *s2, size_t n); +extern "C" int strncmp(const char *s1, const char *s2, size_t n); +extern "C" int strncasecmp(const char *s1, const char *s2, size_t n); +extern "C" char *strncpy(char *dst, const char *src, size_t n); +extern "C" char *strncat(char *dst, const char *src, size_t n); +extern "C" char *strndup(const char *src, size_t n); +extern "C" size_t strlcpy(char *dst, const char *src, size_t size); +extern "C" size_t strlcat(char *dst, const char *src, size_t size); + +void f() { + char b1[80], b2[80]; + if (memset(b1, 0, sizeof(b1) != 0)) {} // \ + expected-warning{{size argument in 'memset' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (memset(b1, 0, sizeof(b1)) != 0) {} + + if (memmove(b1, b2, sizeof(b1) == 0)) {} // \ + expected-warning{{size argument in 'memmove' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (memmove(b1, b2, sizeof(b1)) == 0) {} + + if (memcpy(b1, b2, sizeof(b1) < 0)) {} // \ + expected-warning{{size argument in 'memcpy' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (memcpy(b1, b2, sizeof(b1)) < 0) {} + + if (memcmp(b1, b2, sizeof(b1) <= 0)) {} // \ + expected-warning{{size argument in 'memcmp' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (memcmp(b1, b2, sizeof(b1)) <= 0) {} + + if (strncmp(b1, b2, sizeof(b1) > 0)) {} // \ + expected-warning{{size argument in 'strncmp' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strncmp(b1, b2, sizeof(b1)) > 0) {} + + if (strncasecmp(b1, b2, sizeof(b1) >= 0)) {} // \ + expected-warning{{size argument in 'strncasecmp' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strncasecmp(b1, b2, sizeof(b1)) >= 0) {} + + if (strncpy(b1, b2, sizeof(b1) == 0 || true)) {} // \ + expected-warning{{size argument in 'strncpy' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strncpy(b1, b2, sizeof(b1)) == 0 || true) {} + + if (strncat(b1, b2, sizeof(b1) - 1 >= 0 && true)) {} // \ + expected-warning{{size argument in 'strncat' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {} + + if (strndup(b1, sizeof(b1) != 0)) {} // \ + expected-warning{{size argument in 'strndup' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strndup(b1, sizeof(b1)) != 0) {} + + if (strlcpy(b1, b2, sizeof(b1) != 0)) {} // \ + expected-warning{{size argument in 'strlcpy' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strlcpy(b1, b2, sizeof(b1)) != 0) {} + + if (strlcat(b1, b2, sizeof(b1) != 0)) {} // \ + expected-warning{{size argument in 'strlcat' call is a comparison}} \ + expected-note {{did you mean to compare}} \ + expected-note {{explicitly cast the argument}} + if (strlcat(b1, b2, sizeof(b1)) != 0) {} + + if (memset(b1, 0, sizeof(b1) / 2)) {} + if (memset(b1, 0, sizeof(b1) >> 2)) {} + if (memset(b1, 0, 4 << 2)) {} + if (memset(b1, 0, 4 + 2)) {} + if (memset(b1, 0, 4 - 2)) {} + if (memset(b1, 0, 4 * 2)) {} + + if (memset(b1, 0, (size_t)(sizeof(b1) != 0))) {} +} diff --git a/test/SemaCXX/warn-new-overaligned.cpp b/test/SemaCXX/warn-new-overaligned.cpp index 42a4e3523ad2f..710973ccb32b5 100644 --- a/test/SemaCXX/warn-new-overaligned.cpp +++ b/test/SemaCXX/warn-new-overaligned.cpp @@ -38,7 +38,7 @@ struct Test { } __attribute__((aligned(256))); void* operator new(unsigned long) { - return 0; + return 0; // expected-warning {{'operator new' should not return a null pointer unless it is declared 'throw()'}} } SeparateCacheLines<int> high_contention_data[10]; @@ -59,7 +59,7 @@ struct Test { } __attribute__((aligned(256))); void* operator new[](unsigned long) { - return 0; + return 0; // expected-warning {{'operator new[]' should not return a null pointer unless it is declared 'throw()'}} } SeparateCacheLines<int> high_contention_data[10]; diff --git a/test/SemaCXX/warn-reinterpret-base-class.cpp b/test/SemaCXX/warn-reinterpret-base-class.cpp index 36b8fda553062..0231f194ace2d 100644 --- a/test/SemaCXX/warn-reinterpret-base-class.cpp +++ b/test/SemaCXX/warn-reinterpret-base-class.cpp @@ -1,5 +1,8 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s -// RUN: not %clang_cc1 -std=c++11 -fsyntax-only -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple %itanium_abi_triple -verify -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s + +// RUN: not %clang_cc1 -std=c++11 -fsyntax-only -triple %itanium_abi_triple -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -std=c++11 -fsyntax-only -triple %ms_abi_triple -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s // PR 13824 class A { @@ -288,6 +291,11 @@ void different_subobject_downcast(E *e, F *f, A *a) { (void)reinterpret_cast<I *>(f); // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" +#ifdef MSABI + // In MS ABI mode, A is at non-zero offset in H. + // expected-warning@+3 {{'reinterpret_cast' to class 'H *' from its base at non-zero offset 'A *' behaves differently from 'static_cast'}} + // expected-note@+2 {{use 'static_cast'}} +#endif (void)reinterpret_cast<H *>(a); // expected-warning@+2 {{'reinterpret_cast' to class 'L' (aka 'const F *volatile') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}} @@ -309,6 +317,12 @@ void different_subobject_upcast(F *f, G *g, H *h, I *i) { // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast" (void)reinterpret_cast<E *>(h); + +#ifdef MSABI + // In MS ABI mode, A is at non-zero offset in H. + // expected-warning@+3 {{'reinterpret_cast' from class 'H *' to its base at non-zero offset 'A *' behaves differently from 'static_cast'}} + // expected-note@+2 {{use 'static_cast'}} +#endif (void)reinterpret_cast<A *>(h); // expected-warning@+2 {{'reinterpret_cast' from class 'I *' to its virtual base 'F *' behaves differently from 'static_cast'}} diff --git a/test/SemaCXX/warn-self-assign.cpp b/test/SemaCXX/warn-self-assign.cpp index fcdb2ab6bc639..7d558c6a073e8 100644 --- a/test/SemaCXX/warn-self-assign.cpp +++ b/test/SemaCXX/warn-self-assign.cpp @@ -8,6 +8,9 @@ void f() { b = a = b; a = a = a; // expected-warning{{explicitly assigning}} a = b = b = a; + a &= a; // expected-warning{{explicitly assigning}} + a |= a; // expected-warning{{explicitly assigning}} + a ^= a; } // Dummy type. diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp index 68e9467a937b1..5ad2233d234a0 100644 --- a/test/SemaCXX/warn-shadow.cpp +++ b/test/SemaCXX/warn-shadow.cpp @@ -22,7 +22,7 @@ using namespace xx; using namespace yy; void foo() { - int i; // expected-warning {{declaration shadows a variable in namespace '<anonymous>'}} + int i; // expected-warning {{declaration shadows a variable in namespace '(anonymous)'}} int j; // expected-warning {{declaration shadows a variable in namespace 'one::two'}} int m; } diff --git a/test/SemaCXX/warn-sign-conversion.cpp b/test/SemaCXX/warn-sign-conversion.cpp index ba2bc9b3d026d..746b1242fe1b9 100644 --- a/test/SemaCXX/warn-sign-conversion.cpp +++ b/test/SemaCXX/warn-sign-conversion.cpp @@ -25,23 +25,23 @@ namespace test1 { int c1 = 1 ? i : Foo<bool>::C; int c2 = 1 ? Foo<bool>::C : i; - int d1a = 1 ? i : Foo<bool>::D; // expected-warning {{test1::Foo<bool>::<anonymous enum at }} - int d1b = 1 ? i : Foo<bool>::D; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} - int d2a = 1 ? Foo<bool>::D : i; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::<anonymous enum at }} - int d2b = 1 ? Foo<bool>::D : i; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} - int d3a = 1 ? B : Foo<bool>::D; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::<anonymous enum at }} - int d3b = 1 ? B : Foo<bool>::D; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} - int d4a = 1 ? Foo<bool>::D : B; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::<anonymous enum at }} - int d4b = 1 ? Foo<bool>::D : B; // expected-warning {{warn-sign-conversion.cpp:13:5>' to 'int'}} + int d1a = 1 ? i : Foo<bool>::D; // expected-warning {{test1::Foo<bool>::(anonymous enum at }} + int d1b = 1 ? i : Foo<bool>::D; // expected-warning {{warn-sign-conversion.cpp:13:5)' to 'int'}} + int d2a = 1 ? Foo<bool>::D : i; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::(anonymous enum at }} + int d2b = 1 ? Foo<bool>::D : i; // expected-warning {{warn-sign-conversion.cpp:13:5)' to 'int'}} + int d3a = 1 ? B : Foo<bool>::D; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::(anonymous enum at }} + int d3b = 1 ? B : Foo<bool>::D; // expected-warning {{warn-sign-conversion.cpp:13:5)' to 'int'}} + int d4a = 1 ? Foo<bool>::D : B; // expected-warning {{operand of ? changes signedness: 'test1::Foo<bool>::(anonymous enum at }} + int d4b = 1 ? Foo<bool>::D : B; // expected-warning {{warn-sign-conversion.cpp:13:5)' to 'int'}} - int e1a = 1 ? i : E; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} - int e1b = 1 ? i : E; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} - int e2a = 1 ? E : i; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} - int e2b = 1 ? E : i; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} - int e3a = 1 ? E : B; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} - int e3b = 1 ? E : B; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} - int e4a = 1 ? B : E; // expected-warning {{operand of ? changes signedness: 'test1::<anonymous enum at }} - int e4b = 1 ? B : E; // expected-warning {{warn-sign-conversion.cpp:16:3>' to 'int'}} + int e1a = 1 ? i : E; // expected-warning {{operand of ? changes signedness: 'test1::(anonymous enum at }} + int e1b = 1 ? i : E; // expected-warning {{warn-sign-conversion.cpp:16:3)' to 'int'}} + int e2a = 1 ? E : i; // expected-warning {{operand of ? changes signedness: 'test1::(anonymous enum at }} + int e2b = 1 ? E : i; // expected-warning {{warn-sign-conversion.cpp:16:3)' to 'int'}} + int e3a = 1 ? E : B; // expected-warning {{operand of ? changes signedness: 'test1::(anonymous enum at }} + int e3b = 1 ? E : B; // expected-warning {{warn-sign-conversion.cpp:16:3)' to 'int'}} + int e4a = 1 ? B : E; // expected-warning {{operand of ? changes signedness: 'test1::(anonymous enum at }} + int e4b = 1 ? B : E; // expected-warning {{warn-sign-conversion.cpp:16:3)' to 'int'}} } } diff --git a/test/SemaCXX/warn-string-conversion.cpp b/test/SemaCXX/warn-string-conversion.cpp index 23960e48df619..b26126f6c72f4 100644 --- a/test/SemaCXX/warn-string-conversion.cpp +++ b/test/SemaCXX/warn-string-conversion.cpp @@ -1,14 +1,20 @@ // RUN: %clang_cc1 -fsyntax-only -Wstring-conversion -verify %s // Warn on cases where a string literal is converted into a bool. -// An exception is made for this in logical operators. +// An exception is made for this in logical and operators. void assert(bool condition); void test0() { bool b0 = "hi"; // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} b0 = ""; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}} + b0 = 0 || ""; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}} + b0 = "" || 0; // expected-warning{{implicit conversion turns string literal into bool: 'const char [1]' to 'bool'}} b0 = 0 && ""; + b0 = "" && 0; assert("error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}} + assert(0 || "error"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}} + assert("error" || 0); // expected-warning{{implicit conversion turns string literal into bool: 'const char [6]' to 'bool'}} assert(0 && "error"); + assert("error" && 0); while("hi") {} // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} do {} while("hi"); // expected-warning{{implicit conversion turns string literal into bool: 'const char [3]' to 'bool'}} diff --git a/test/SemaCXX/warn-sysheader-macro.cpp b/test/SemaCXX/warn-sysheader-macro.cpp new file mode 100644 index 0000000000000..c88461720ad4d --- /dev/null +++ b/test/SemaCXX/warn-sysheader-macro.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wshadow -Wold-style-cast %s + +// Test that macro expansions from system headers don't trigger 'syntactic' +// warnings that are not actionable. + +#ifdef IS_SYSHEADER +#pragma clang system_header + +#define SANITY(a) (a / 0) + +#define SHADOW(a) __extension__({ int v = a; v; }) + +#define OLD_STYLE_CAST(a) ((int) (a)) + +#else + +#define IS_SYSHEADER +#include __FILE__ + +void testSanity() { + // Validate that the test is set up correctly + int i = SANITY(0); // expected-warning {{division by zero is undefined}} +} + +void PR16093() { + // no -Wshadow in system macro expansion + int i = SHADOW(SHADOW(1)); +} + +void PR18147() { + // no -Wold_style_cast in system macro expansion + int i = OLD_STYLE_CAST(0); +} + +#endif diff --git a/test/SemaCXX/warn-tautological-compare.cpp b/test/SemaCXX/warn-tautological-compare.cpp new file mode 100644 index 0000000000000..b44f3f9d8fa34 --- /dev/null +++ b/test/SemaCXX/warn-tautological-compare.cpp @@ -0,0 +1,138 @@ +// Force x86-64 because some of our heuristics are actually based +// on integer sizes. + +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -verify -std=c++11 %s + +namespace RuntimeBehavior { + // Avoid emitting tautological compare warnings when the code already has + // compile time checks on variable sizes. + + const int kintmax = 2147483647; + void test0(short x) { + if (sizeof(x) < sizeof(int) || x < kintmax) {} + + if (x < kintmax) {} + // expected-warning@-1{{comparison of constant 2147483647 with expression of type 'short' is always true}} + } + + void test1(short x) { + if (x < kintmax) {} + // expected-warning@-1{{comparison of constant 2147483647 with expression of type 'short' is always true}} + + if (sizeof(x) < sizeof(int)) + return; + + if (x < kintmax) {} + } +} + +namespace ArrayCompare { + #define GetValue(ptr) ((ptr != 0) ? ptr[0] : 0) + extern int a[] __attribute__((weak)); + int b[] = {8,13,21}; + struct { + int x[10]; + } c; + const char str[] = "text"; + void ignore() { + if (a == 0) {} + if (a != 0) {} + (void)GetValue(b); + } + void test() { + if (b == 0) {} + // expected-warning@-1{{comparison of array 'b' equal to a null pointer is always false}} + if (b != 0) {} + // expected-warning@-1{{comparison of array 'b' not equal to a null pointer is always true}} + if (0 == b) {} + // expected-warning@-1{{comparison of array 'b' equal to a null pointer is always false}} + if (0 != b) {} + // expected-warning@-1{{comparison of array 'b' not equal to a null pointer is always true}} + if (c.x == 0) {} + // expected-warning@-1{{comparison of array 'c.x' equal to a null pointer is always false}} + if (c.x != 0) {} + // expected-warning@-1{{comparison of array 'c.x' not equal to a null pointer is always true}} + if (str == 0) {} + // expected-warning@-1{{comparison of array 'str' equal to a null pointer is always false}} + if (str != 0) {} + // expected-warning@-1{{comparison of array 'str' not equal to a null pointer is always true}} + } +} + +namespace FunctionCompare { + #define CallFunction(f) ((f != 0) ? f() : 0) + extern void a() __attribute__((weak)); + void fun1(); + int fun2(); + int* fun3(); + int* fun4(int); + class S { + public: + static int foo(); + }; + void ignore() { + if (a == 0) {} + if (0 != a) {} + (void)CallFunction(fun2); + } + void test() { + if (fun1 == 0) {} + // expected-warning@-1{{comparison of function 'fun1' equal to a null pointer is always false}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + if (fun2 == 0) {} + // expected-warning@-1{{comparison of function 'fun2' equal to a null pointer is always false}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + // expected-note@-3{{suffix with parentheses to turn this into a function call}} + if (fun3 == 0) {} + // expected-warning@-1{{comparison of function 'fun3' equal to a null pointer is always false}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + // expected-note@-3{{suffix with parentheses to turn this into a function call}} + if (fun4 == 0) {} + // expected-warning@-1{{comparison of function 'fun4' equal to a null pointer is always false}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + if (nullptr != fun1) {} + // expected-warning@-1{{comparison of function 'fun1' not equal to a null pointer is always true}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + if (nullptr != fun2) {} + // expected-warning@-1{{comparison of function 'fun2' not equal to a null pointer is always true}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + if (nullptr != fun3) {} + // expected-warning@-1{{comparison of function 'fun3' not equal to a null pointer is always true}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + // expected-note@-3{{suffix with parentheses to turn this into a function call}} + if (nullptr != fun4) {} + // expected-warning@-1{{comparison of function 'fun4' not equal to a null pointer is always true}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + if (S::foo == 0) {} + // expected-warning@-1{{comparison of function 'S::foo' equal to a null pointer is always false}} + // expected-note@-2{{prefix with the address-of operator to silence this warning}} + // expected-note@-3{{suffix with parentheses to turn this into a function call}} + } +} + +namespace PointerCompare { + extern int a __attribute__((weak)); + int b; + static int c; + class S { + public: + static int a; + int b; + }; + void ignored() { + if (&a == 0) {} + } + void test() { + S s; + if (&b == 0) {} + // expected-warning@-1{{comparison of address of 'b' equal to a null pointer is always false}} + if (&c == 0) {} + // expected-warning@-1{{comparison of address of 'c' equal to a null pointer is always false}} + if (&s.a == 0) {} + // expected-warning@-1{{comparison of address of 's.a' equal to a null pointer is always false}} + if (&s.b == 0) {} + // expected-warning@-1{{comparison of address of 's.b' equal to a null pointer is always false}} + if (&S::a == 0) {} + // expected-warning@-1{{comparison of address of 'S::a' equal to a null pointer is always false}} + } +} diff --git a/test/SemaCXX/warn-tautological-undefined-compare.cpp b/test/SemaCXX/warn-tautological-undefined-compare.cpp new file mode 100644 index 0000000000000..ce05bfc14d170 --- /dev/null +++ b/test/SemaCXX/warn-tautological-undefined-compare.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wtautological-undefined-compare %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-tautological-compare -Wtautological-undefined-compare %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wtautological-compare %s + +void test1(int &x) { + if (x == 1) { } + if (&x == 0) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&x != 0) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} +} + +class test2 { + test2() : x(y) {} + + void foo() { + if (this == 0) { } + // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (this != 0) { } + // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to true}} + } + + void bar() { + if (x == 1) { } + if (&x == 0) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&x != 0) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + } + + int &x; + int y; +}; + +namespace function_return_reference { + int& get_int(); + // expected-note@-1 4{{'get_int' returns a reference}} + class B { + public: + static int &stat(); + // expected-note@-1 4{{'stat' returns a reference}} + int &get(); + // expected-note@-1 8{{'get' returns a reference}} + }; + + void test() { + if (&get_int() == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&(get_int()) == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + + if (&get_int() != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + if (&(get_int()) != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + + if (&B::stat() == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&(B::stat()) == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + + if (&B::stat() != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + if (&(B::stat()) != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + + B b; + if (&b.get() == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&(b.get()) == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + + if (&b.get() != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + if (&(b.get()) != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + + B* b_ptr = &b; + if (&b_ptr->get() == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&(b_ptr->get()) == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + + if (&b_ptr->get() != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + if (&(b_ptr->get()) != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + + int& (B::*m_ptr)() = &B::get; + if (&(b.*m_ptr)() == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&((b.*m_ptr)()) == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + + if (&(b.*m_ptr)() != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + if (&((b.*m_ptr)()) != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + + int& (*f_ptr)() = &get_int; + if (&(*f_ptr)() == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + if (&((*f_ptr)()) == 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}} + + if (&(*f_ptr)() != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + if (&((*f_ptr)()) != 0) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}} + } +} diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index ce6250d6da905..34a33aab42d26 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -208,33 +208,33 @@ void sls_fun_good_8() { void sls_fun_bad_1() { sls_mu.Unlock(); // \ - // expected-warning{{unlocking 'sls_mu' that was not locked}} + // expected-warning{{releasing mutex 'sls_mu' that was not held}} } void sls_fun_bad_2() { sls_mu.Lock(); sls_mu.Lock(); // \ - // expected-warning{{locking 'sls_mu' that is already locked}} + // expected-warning{{acquiring mutex 'sls_mu' that is already held}} sls_mu.Unlock(); } void sls_fun_bad_3() { sls_mu.Lock(); // expected-note {{mutex acquired here}} -} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} +} // expected-warning{{mutex 'sls_mu' is still held at the end of function}} void sls_fun_bad_4() { if (getBool()) 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}} \ - // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} +} // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \ + // expected-warning{{mutex 'sls_mu2' is not held on every path through here}} void sls_fun_bad_5() { sls_mu.Lock(); // expected-note {{mutex acquired here}} if (getBool()) sls_mu.Unlock(); -} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} +} // expected-warning{{mutex 'sls_mu' is not held on every path through here}} void sls_fun_bad_6() { if (getBool()) { @@ -247,8 +247,8 @@ void sls_fun_bad_6() { } } sls_mu.Unlock(); // \ - expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\ - expected-warning{{unlocking 'sls_mu' that was not locked}} + expected-warning{{mutex 'sls_mu' is not held on every path through here}}\ + expected-warning{{releasing mutex 'sls_mu' that was not held}} } void sls_fun_bad_7() { @@ -258,7 +258,7 @@ void sls_fun_bad_7() { if (getBool()) { if (getBool()) { continue; // \ - expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} } } sls_mu.Lock(); // expected-note {{mutex acquired here}} @@ -270,14 +270,14 @@ void sls_fun_bad_8() { sls_mu.Lock(); // expected-note{{mutex acquired here}} do { - sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} } while (getBool()); } void sls_fun_bad_9() { do { sls_mu.Lock(); // \ - // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \ + // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \ // expected-note{{mutex acquired here}} } while (getBool()); sls_mu.Unlock(); @@ -285,18 +285,18 @@ void sls_fun_bad_9() { void sls_fun_bad_10() { 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}} + while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} sls_mu.Unlock(); } -} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} +} // expected-warning{{mutex 'sls_mu' is still held 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 held at start of each loop}} sls_mu.Lock(); // expected-note {{mutex acquired here}} } sls_mu.Unlock(); // \ - // expected-warning{{unlocking 'sls_mu' that was not locked}} + // expected-warning{{releasing mutex 'sls_mu' that was not held}} } void sls_fun_bad_12() { @@ -305,7 +305,7 @@ void sls_fun_bad_12() { sls_mu.Unlock(); if (getBool()) { if (getBool()) { - break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} + break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}} } } sls_mu.Lock(); @@ -334,19 +334,19 @@ void aa_fun_1() { void aa_fun_bad_1() { glock.globalUnlock(); // \ - // expected-warning{{unlocking 'aa_mu' that was not locked}} + // expected-warning{{releasing mutex 'aa_mu' that was not held}} } void aa_fun_bad_2() { glock.globalLock(); glock.globalLock(); // \ - // expected-warning{{locking 'aa_mu' that is already locked}} + // expected-warning{{acquiring mutex 'aa_mu' that is already held}} glock.globalUnlock(); } void aa_fun_bad_3() { glock.globalLock(); // expected-note{{mutex acquired here}} -} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}} +} // expected-warning{{mutex 'aa_mu' is still held at the end of function}} //--------------------------------------------------// // Regression tests for unusual method names @@ -359,17 +359,17 @@ class WeirdMethods { // FIXME: can't currently check inside constructors and destructors. WeirdMethods() { wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}} - } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}} + } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}} ~WeirdMethods() { wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}} - } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}} + } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}} void operator++() { wmu.Lock(); // expected-note {{mutex acquired here}} - } // expected-warning {{mutex 'wmu' is still locked at the end of function}} + } // expected-warning {{mutex 'wmu' is still held at the end of function}} operator int*() { wmu.Lock(); // expected-note {{mutex acquired here}} return 0; - } // expected-warning {{mutex 'wmu' is still locked at the end of function}} + } // expected-warning {{mutex 'wmu' is still held at the end of function}} }; //-----------------------------------------------// @@ -386,13 +386,13 @@ class PGBFoo { __attribute__((pt_guarded_by(sls_mu))); void testFoo() { pgb_field = &x; // \ - // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}} - *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \ - // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}} - x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \ - // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}} - (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \ - // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}} + // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}} + *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \ + // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}} + x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \ + // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}} + (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \ + // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}} } }; @@ -402,7 +402,7 @@ class GBFoo { void testFoo() { gb_field = 0; // \ - // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}} + // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}} } void testNoAnal() __attribute__((no_thread_safety_analysis)) { @@ -435,59 +435,59 @@ void gb_fun_3() { void gb_bad_0() { sls_guard_var = 1; // \ - // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} + // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}} } void gb_bad_1() { int x = sls_guard_var; // \ - // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}} + // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}} } void gb_bad_2() { sls_guardby_var = 1; // \ - // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}} + // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}} } void gb_bad_3() { int x = sls_guardby_var; // \ - // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}} + // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}} } void gb_bad_4() { *pgb_gvar = 1; // \ - // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}} + // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}} } void gb_bad_5() { int x = *pgb_gvar; // \ - // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}} + // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}} } void gb_bad_6() { *pgb_var = 1; // \ - // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}} + // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}} } void gb_bad_7() { int x = *pgb_var; // \ - // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}} + // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}} } void gb_bad_8() { GBFoo G; G.gb_field = 0; // \ - // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}} + // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}} } void gb_bad_9() { sls_guard_var++; // \ - // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} + // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}} sls_guard_var--; // \ - // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} + // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}} ++sls_guard_var; // \ - // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} + // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}} --sls_guard_var;// \ - // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}} + // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}} } //-----------------------------------------------// @@ -503,11 +503,11 @@ public: void test() { a = 0; // \ - // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}} + // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}} b = a; // \ - // expected-warning {{reading variable 'a' requires locking 'mu'}} + // expected-warning {{reading variable 'a' requires holding mutex 'mu'}} c = 0; // \ - // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}} + // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}} } int c __attribute__((guarded_by(mu))); @@ -549,7 +549,7 @@ void late_bad_0() { LateFoo fooB; fooA.mu.Lock(); fooB.a = 5; // \ - // expected-warning{{writing variable 'a' requires locking 'fooB.mu' exclusively}} \ + // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \ // expected-note{{found near match 'fooA.mu'}} fooA.mu.Unlock(); } @@ -560,7 +560,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 'b1.mu'}} + // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}} b1.mu1_.Unlock(); b1.b_ = res; mu.Unlock(); @@ -570,7 +570,7 @@ void late_bad_2() { LateBar BarA; BarA.FooPointer->mu.Lock(); BarA.Foo.a = 2; // \ - // expected-warning{{writing variable 'a' requires locking 'BarA.Foo.mu' exclusively}} \ + // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \ // expected-note{{found near match 'BarA.FooPointer->mu'}} BarA.FooPointer->mu.Unlock(); } @@ -579,7 +579,7 @@ void late_bad_3() { LateBar BarA; BarA.Foo.mu.Lock(); BarA.FooPointer->a = 2; // \ - // expected-warning{{writing variable 'a' requires locking 'BarA.FooPointer->mu' exclusively}} \ + // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \ // expected-note{{found near match 'BarA.Foo.mu'}} BarA.Foo.mu.Unlock(); } @@ -588,7 +588,7 @@ void late_bad_4() { LateBar BarA; BarA.Foo.mu.Lock(); BarA.Foo2.a = 2; // \ - // expected-warning{{writing variable 'a' requires locking 'BarA.Foo2.mu' exclusively}} \ + // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \ // expected-note{{found near match 'BarA.Foo.mu'}} BarA.Foo.mu.Unlock(); } @@ -608,11 +608,11 @@ void shared_fun_0() { void shared_fun_1() { sls_mu.ReaderLock(); // \ - // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} + // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}} do { sls_mu.Unlock(); sls_mu.Lock(); // \ - // expected-note {{the other lock of mutex 'sls_mu' is here}} + // expected-note {{the other acquisition of mutex 'sls_mu' is here}} } while (getBool()); sls_mu.Unlock(); } @@ -638,20 +638,20 @@ void shared_fun_4() { void shared_fun_8() { if (getBool()) sls_mu.Lock(); // \ - // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} + // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}} else sls_mu.ReaderLock(); // \ - // expected-note {{the other lock of mutex 'sls_mu' is here}} + // expected-note {{the other acquisition of mutex 'sls_mu' is here}} sls_mu.Unlock(); } void shared_bad_0() { sls_mu.Lock(); // \ - // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} + // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}} do { sls_mu.Unlock(); sls_mu.ReaderLock(); // \ - // expected-note {{the other lock of mutex 'sls_mu' is here}} + // expected-note {{the other acquisition of mutex 'sls_mu' is here}} } while (getBool()); sls_mu.Unlock(); } @@ -659,10 +659,10 @@ void shared_bad_0() { void shared_bad_1() { if (getBool()) sls_mu.Lock(); // \ - // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} + // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}} else sls_mu.ReaderLock(); // \ - // expected-note {{the other lock of mutex 'sls_mu' is here}} + // expected-note {{the other acquisition of mutex 'sls_mu' is here}} *pgb_var = 1; sls_mu.Unlock(); } @@ -670,10 +670,10 @@ void shared_bad_1() { void shared_bad_2() { if (getBool()) sls_mu.ReaderLock(); // \ - // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}} + // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}} else sls_mu.Lock(); // \ - // expected-note {{the other lock of mutex 'sls_mu' is here}} + // expected-note {{the other acquisition of mutex 'sls_mu' is here}} *pgb_var = 1; sls_mu.Unlock(); } @@ -762,49 +762,49 @@ void es_fun_10() { void es_bad_0() { Bar.aa_elr_fun(); // \ - // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}} + // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}} } void es_bad_1() { aa_mu.ReaderLock(); Bar.aa_elr_fun(); // \ - // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}} + // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}} aa_mu.Unlock(); } void es_bad_2() { Bar.aa_elr_fun_s(); // \ - // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}} + // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}} } void es_bad_3() { MyLRFoo.test(); // \ - // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}} + // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}} } void es_bad_4() { MyLRFoo.testShared(); // \ - // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}} + // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}} } void es_bad_5() { sls_mu.ReaderLock(); MyLRFoo.test(); // \ - // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}} + // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}} sls_mu.Unlock(); } void es_bad_6() { sls_mu.Lock(); Bar.le_fun(); // \ - // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}} + // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}} sls_mu.Unlock(); } void es_bad_7() { sls_mu.ReaderLock(); Bar.le_fun(); // \ - // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}} + // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}} sls_mu.Unlock(); } @@ -1209,7 +1209,7 @@ void Foo::bar() { int x; mu_.Lock(); - x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}} + x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}} a_ = x + 1; mu_.Unlock(); if (x > 5) { @@ -1223,13 +1223,13 @@ void main() { Foo f1, *f2; f1.mu_.Lock(); - f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is locked}} + f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}} mu2.Lock(); f1.foo(); mu2.Unlock(); f1.mu_.Unlock(); f2->mu_.Lock(); - f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is locked}} + f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}} f2->mu_.Unlock(); mu2.Lock(); w = 2; @@ -1258,7 +1258,7 @@ void func() b1->MyLock(); b1->a_ = 5; b2->a_ = 3; // \ - // expected-warning {{writing variable 'a_' requires locking 'b2->mu1_' exclusively}} \ + // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \ // expected-note {{found near match 'b1->mu1_'}} b2->MyLock(); b2->MyUnlock(); @@ -1288,18 +1288,18 @@ int func(int i) { int x; b3->mu1_.Lock(); - res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'b1.mu1_'}} \ - // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}} \ + res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \ + // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \ // expected-note {{found near match 'b3->mu1_'}} - *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 'b1.mu1_' exclusively}} \ + *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \ + // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}} + b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \ + // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \ // expected-note {{found near match 'b3->mu1_'}} - b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}} + b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}} b3->mu1_.Unlock(); - b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}} - x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}} + b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} + x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} return x; } } // end namespace thread_annot_lock_21 @@ -1321,10 +1321,10 @@ 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 'child->lock_'}} \ + // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \ // expected-note {{found near match 'lock_'}} child->a_ = 5; // \ - // expected-warning {{writing variable 'a_' requires locking 'child->lock_' exclusively}} \ + // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \ // expected-note {{found near match 'lock_'}} lock_.Unlock(); } @@ -1362,7 +1362,7 @@ void Foo::Func(Foo* child) { lock_.Lock(); child->lock_.Lock(); - child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is locked}} + child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}} child->bar(7); child->a_ = 5; child->lock_.Unlock(); @@ -1401,8 +1401,8 @@ class Foo { public: void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) { x = 5; - f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \ - // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}} + f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \ + // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}} } }; @@ -1410,8 +1410,8 @@ Foo *foo; void func() { - foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu2'}} \ - // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu1'}} + foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \ + // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}} } } // end namespace thread_annot_lock_42 @@ -1434,14 +1434,14 @@ void main() { Child *c; Base *b = c; - b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'b->mu_'}} + b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'b->mu_' exclusively}} b->mu_.Lock(); - b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is locked}} + b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is held}} b->mu_.Unlock(); - c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'c->mu_'}} + c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}} c->mu_.Lock(); - c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is locked}} + c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}} c->mu_.Unlock(); } } // end namespace thread_annot_lock_46 @@ -1468,10 +1468,10 @@ int Foo::method1(int i) { void main() { Foo a; - 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 'a.mu2'}} \ - // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}} + a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \ + // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \ + // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \ + // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}} } } // end namespace thread_annot_lock_67_modified @@ -1516,14 +1516,14 @@ namespace substitution_test { DataLocker dlr; dlr.lockData(d1); // expected-note {{mutex acquired here}} dlr.unlockData(d2); // \ - // expected-warning {{unlocking 'd2->mu' that was not locked}} - } // expected-warning {{mutex 'd1->mu' is still locked at the end of function}} + // expected-warning {{releasing mutex 'd2->mu' that was not held}} + } // expected-warning {{mutex 'd1->mu' is still held 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 'd2->mu'}} \ + // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \ // expected-note {{found near match 'd1->mu'}} dlr.unlockData(d1); } @@ -1566,8 +1566,8 @@ namespace template_member_test { template<typename U> struct IndirectLock { int DoNaughtyThings(T *t) { - u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}} - return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}} + u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}} + return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}} } }; @@ -1583,7 +1583,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 'v.m'}} + v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}} } }; template struct W<int>; // expected-note {{here}} @@ -1620,7 +1620,7 @@ struct TestScopedLockable { void foo3() { MutexLock mulock_a(&mu1); MutexLock mulock_b(&mu1); // \ - // expected-warning {{locking 'mu1' that is already locked}} + // expected-warning {{acquiring mutex 'mu1' that is already held}} } void foo4() { @@ -1646,7 +1646,7 @@ Foo fooObj; void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_); void bar() { - foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}} + foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}} fooObj.mu_.Lock(); foo(); fooObj.mu_.Unlock(); @@ -1722,7 +1722,7 @@ struct TestTryLock { if (cond) b = true; 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}} + a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}} } if (b2) { // b2 should be known at this point. a = 8; @@ -1748,7 +1748,7 @@ struct TestTryLock { while (cond) { if (b) { // b should be uknown at this point b/c of the loop - a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}} + a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}} } b = !b; } @@ -1876,7 +1876,7 @@ void test() { f1.mu_.Unlock(); bt.barTD(&f1); // \ - // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}} \ + // expected-warning {{calling function 'barTD' requires holding mutex 'f1.mu_' exclusively}} \ // expected-note {{found near match 'bt.fooBase.mu_'}} bt.fooBase.mu_.Unlock(); @@ -1885,7 +1885,7 @@ void test() { Cell<int> cell; cell.data = 0; // \ - // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}} + // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}} cell.foo(); cell.mu_.Lock(); cell.fooEx(); @@ -1954,7 +1954,7 @@ void Foo::foo1(Foo *f_defined) { void test() { Foo myfoo; myfoo.foo1(&myfoo); // \ - // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}} + // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}} myfoo.mu_.Lock(); myfoo.foo1(&myfoo); myfoo.mu_.Unlock(); @@ -1980,7 +1980,7 @@ namespace GoingNative { if (bar()) { // ... if (foo()) - continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}} + continue; // expected-warning {{expecting mutex 'm' to be held at start of each loop}} //... } // ... @@ -2069,21 +2069,21 @@ void test() { Foo myFoo; myFoo.foo2(); // \ - // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}} myFoo.foo3(&myFoo); // \ - // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}} myFoo.fooT1(dummy); // \ - // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'fooT1' requires holding mutex 'myFoo.mu_' exclusively}} myFoo.fooT2(dummy); // \ - // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'fooT2' requires holding mutex 'myFoo.mu_' exclusively}} fooF1(&myFoo); // \ - // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}} fooF2(&myFoo); // \ - // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}} fooF3(&myFoo); // \ - // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}} + // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}} myFoo.mu_.Lock(); myFoo.foo2(); @@ -2099,7 +2099,7 @@ void test() { FooT<int> myFooT; myFooT.foo(); // \ - // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}} + // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}} } } // end namespace FunctionDefinitionTest @@ -2127,7 +2127,7 @@ public: void test() { foo = 2; // \ - // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}} + // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}} } }; @@ -2192,11 +2192,11 @@ public: void foo() { a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} b = 0; // \ - // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}} c = 0; // \ - // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}} } private: @@ -2283,31 +2283,31 @@ void test() { bar.getFoo().mu_.Lock(); bar.getFooey().a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}} \ + // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \ // expected-note {{found near match 'bar.getFoo().mu_'}} bar.getFoo().mu_.Unlock(); bar.getFoo2(a).mu_.Lock(); bar.getFoo2(b).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}} \ + // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \ // expected-note {{found near match 'bar.getFoo2(a).mu_'}} bar.getFoo2(a).mu_.Unlock(); bar.getFoo3(a, b).mu_.Lock(); bar.getFoo3(a, c).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}} \ + // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a,c).mu_' exclusively}} \ // expected-note {{'bar.getFoo3(a,b).mu_'}} bar.getFoo3(a, b).mu_.Unlock(); getBarFoo(bar, a).mu_.Lock(); getBarFoo(bar, b).a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}} \ + // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar,b).mu_' exclusively}} \ // expected-note {{'getBarFoo(bar,a).mu_'}} 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 '((a#_)#_#fooArray[b]).mu_' exclusively}} \ + // expected-warning {{writing variable 'a' requires holding mutex '((a#_)#_#fooArray[b]).mu_' exclusively}} \ // expected-note {{'((a#_)#_#fooArray[_]).mu_'}} (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); } @@ -2356,19 +2356,19 @@ public: // 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->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}} + f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}} - 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->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \ + // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} + Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}} f1->getMu()->Lock(); f1->a = 0; f1->foo(); f1->foo2(f2); // \ - // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} \ + // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \ // expected-note {{found near match 'f1->mu_'}} Foo::getMu(f2)->Lock(); @@ -2398,19 +2398,19 @@ public: // 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->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}} + b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}} + b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \ + // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} + Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}} + Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}} b1->getMu()->Lock(); b1->b = 0; b1->bar(); b1->bar2(b2); // \ - // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} \ + // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \ // // expected-note {{found near match 'b1->mu_'}} b2->getMu()->Lock(); @@ -2476,13 +2476,13 @@ void Foo::test3() { ReleasableMutexLock rlock(&mu_); a = 0; rlock.Release(); - a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} } void Foo::test4() { ReleasableMutexLock rlock(&mu_); rlock.Release(); - rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}} + rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}} } void Foo::test5() { @@ -2491,7 +2491,7 @@ void Foo::test5() { rlock.Release(); } // no warning on join point for managed lock. - rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}} + rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}} } @@ -2560,12 +2560,12 @@ public: 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}} + } // expected-warning {{expecting mutex 'mutex_' to be held 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}} + } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}} }; } // end namespace UnlockBug @@ -2599,7 +2599,7 @@ class Foo { void test2() { WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}} - } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + } // expected-warning {{mutex 'mu_' is still held at the end of function}} void test3() { if (c) { @@ -2622,7 +2622,7 @@ class Foo { if (c) { WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}} } - } // expected-warning {{mutex 'mu_' is not locked on every path through here}} + } // expected-warning {{mutex 'mu_' is not held on every path through here}} void test6() { if (c) { @@ -2631,7 +2631,7 @@ class Foo { else { WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}} } - } // expected-warning {{mutex 'mu_' is not locked on every path through here}} + } // expected-warning {{mutex 'mu_' is not held on every path through here}} }; @@ -2655,7 +2655,7 @@ void Foo::test() { ReaderMutexLock lock(getMutexPtr().get()); int b = a; } - int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}} + int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}} } } // end namespace TemporaryCleanupExpr @@ -2686,9 +2686,9 @@ public: }; 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}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} + b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}} + c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}} } void Foo::test1() { @@ -2772,10 +2772,10 @@ void Foo::test7() { 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()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}} + (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}} mu_.get()->Unlock(); - Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}} + Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}} } @@ -2790,9 +2790,9 @@ class Bar { 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}} + foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}} + (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}} + foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}} } @@ -2906,9 +2906,9 @@ void test0() { foo.unlock(); foo.lock(); - foo.lock(); // expected-warning {{locking 'foo' that is already locked}} + foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}} foo.unlock(); - foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}} + foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}} } @@ -2919,10 +2919,10 @@ void test1() { foo.unlock1(); foo.lock1(); - foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}} + foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} foo.a = 0; foo.unlock1(); - foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}} + foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} } @@ -2933,10 +2933,10 @@ int test2() { foo.unlock1(); foo.slock1(); - foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}} + foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} int d2 = foo.a; foo.unlock1(); - foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}} + foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} return d1 + d2; } @@ -2951,17 +2951,17 @@ void test3() { 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}} + // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \ + // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \ + // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}} 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}} + // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \ + // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \ + // expected-warning {{releasing mutex 'foo.mu3_' that was not held}} } @@ -2975,17 +2975,17 @@ void testlots() { 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}} + // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \ + // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \ + // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}} 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}} + // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \ + // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \ + // expected-warning {{releasing mutex 'foo.mu3_' that was not held}} } } // end namespace DuplicateAttributeTest @@ -3010,7 +3010,7 @@ class Foo { void Foo::test1() { if (tryLockMutexP() == 0) { - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} return; } a = 0; @@ -3032,14 +3032,14 @@ void Foo::test1() { } if (tryLockMutexI() == 0) { - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} return; } a = 0; unlock(); if (0 == tryLockMutexI()) { - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} return; } a = 0; @@ -3051,7 +3051,7 @@ void Foo::test1() { } if (mu_.TryLock() == false) { - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} return; } a = 0; @@ -3062,12 +3062,12 @@ void Foo::test1() { unlock(); } else { - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} } #if __has_feature(cxx_nullptr) if (tryLockMutexP() == nullptr) { - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} return; } a = 0; @@ -3103,26 +3103,26 @@ void test() { 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.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}} + n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}} 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}} + n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}} 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}} + n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}} g2.mu_.Unlock(); LockAllGraphs(); n1.a = 0; n1.foo(); - n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}} + n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}} UnlockAllGraphs(); LockAllGraphs(); @@ -3132,7 +3132,7 @@ void test() { g2.mu_.Unlock(); LockAllGraphs(); - g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}} + g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}} g1.mu_.Unlock(); } @@ -3260,9 +3260,9 @@ class Foo { beginNoWarnOnWrites(); } a = 0; // \ - // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} endNoWarnOnWrites(); // \ - // expected-warning {{unlocking '*' that was not locked}} + // expected-warning {{releasing mutex '*' that was not held}} } @@ -3390,17 +3390,17 @@ public: void test1() { - Foo f; // expected-warning {{calling function 'Foo' requires exclusive lock on 'mu_'}} - int a = f[0]; // expected-warning {{calling function 'operator[]' requires exclusive lock on 'mu_'}} -} // expected-warning {{calling function '~Foo' requires exclusive lock on 'mu_'}} + Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}} + int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}} +} // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}} void test2() { Bar::mu_.Lock(); { - Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is locked}} - int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is locked}} - } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is locked}} + Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}} + int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}} + } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}} Bar::mu_.Unlock(); } @@ -3499,7 +3499,7 @@ void Foo::elr(Cell<T>* c1) { } void Foo::test() { Cell<int> cell; elr(&cell); // \ - // expected-warning {{calling function 'elr' requires exclusive lock on 'cell.mu_'}} + // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}} } @@ -3512,7 +3512,7 @@ void globalELR(Cell<T>* c1) { } void globalTest() { Cell<int> cell; globalELR(&cell); // \ - // expected-warning {{calling function 'globalELR' requires exclusive lock on 'cell.mu_'}} + // expected-warning {{calling function 'globalELR' requires holding mutex 'cell.mu_' exclusively}} } @@ -3533,7 +3533,7 @@ void globalELR2(Cell<T>* c4); void globalTest2() { Cell<int> cell; globalELR2(&cell); // \ - // expected-warning {{calling function 'globalELR2' requires exclusive lock on 'cell.mu_'}} + // expected-warning {{calling function 'globalELR2' requires holding mutex 'cell.mu_' exclusively}} } @@ -3550,7 +3550,7 @@ void testFooT() { Cell<int> cell; FooT<int> foo; foo.elr(&cell); // \ - // expected-warning {{calling function 'elr' requires exclusive lock on 'cell.mu_'}} + // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}} } } // end namespace TemplateFunctionParamRemapTest @@ -3616,8 +3616,14 @@ class Foo { EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_); bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_) SHARED_TRYLOCK_FUNCTION(true, mu2_); + void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_) + ASSERT_EXCLUSIVE_LOCK(mu2_); + void assertShared() ASSERT_SHARED_LOCK(mu1_) + ASSERT_SHARED_LOCK(mu2_); void test(); + void testAssert(); + void testAssertShared(); }; @@ -3676,6 +3682,21 @@ void Foo::test() { } } +// Force duplication of attributes +void Foo::assertBoth() { } +void Foo::assertShared() { } + +void Foo::testAssert() { + assertBoth(); + a = 0; + b = 0; +} + +void Foo::testAssertShared() { + assertShared(); + int zz = a + b; +} + } // end namespace MultipleAttributeTest @@ -3717,24 +3738,24 @@ public: // method call tests void test() { data_.setValue(0); // FIXME -- should be writing \ - // expected-warning {{reading variable 'data_' requires locking 'mu_'}} + // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} int a = data_.getValue(); // \ - // expected-warning {{reading variable 'data_' requires locking 'mu_'}} + // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} datap1_->setValue(0); // FIXME -- should be writing \ - // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}} + // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} a = datap1_->getValue(); // \ - // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}} + // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} datap2_->setValue(0); // FIXME -- should be writing \ - // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} a = datap2_->getValue(); // \ - // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} (*datap2_).setValue(0); // FIXME -- should be writing \ - // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} a = (*datap2_).getValue(); // \ - // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} mu_.Lock(); data_.setValue(1); @@ -3752,31 +3773,31 @@ public: // operator tests void test2() { - data_ = Data(1); // expected-warning {{writing variable 'data_' requires locking 'mu_' exclusively}} - *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}} \ - // expected-warning {{reading variable 'data_' requires locking 'mu_'}} - *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires locking 'mu_' exclusively}} \ - // expected-warning {{reading variable 'data_' requires locking 'mu_'}} - data_ = *datap1_; // expected-warning {{writing variable 'data_' requires locking 'mu_' exclusively}} \ - // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}} - data_ = *datap2_; // expected-warning {{writing variable 'data_' requires locking 'mu_' exclusively}} \ - // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} + *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \ + // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} + *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \ + // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} + data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \ + // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} + data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \ + // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} - data_[0] = 0; // expected-warning {{reading variable 'data_' requires locking 'mu_'}} - (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} + (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} - data_(); // expected-warning {{reading variable 'data_' requires locking 'mu_'}} + data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} } // const operator tests void test3() const { - Data mydat(data_); // expected-warning {{reading variable 'data_' requires locking 'mu_'}} + Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} //FIXME - //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires locking 'mu_'}} - //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}} + //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} + //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}} - int a = data_[0]; // expected-warning {{reading variable 'data_' requires locking 'mu_'}} + int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}} } private: @@ -3820,31 +3841,31 @@ private: Foo* foop PT_GUARDED_BY(mu_); void test() { - foo.myMethod(); // expected-warning {{reading variable 'foo' requires locking 'mu_'}} + foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} - int fa = foo.a; // expected-warning {{reading variable 'foo' requires locking 'mu_'}} - foo.a = fa; // expected-warning {{writing variable 'foo' requires locking 'mu_' exclusively}} + int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} + foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}} - fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}} - foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_' exclusively}} + fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} + foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}} - fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}} - (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_' exclusively}} + fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} + (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}} - foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires locking 'mu_'}} \ - // expected-warning {{writing variable 'c' requires locking 'foo.cell_mu_' exclusively}} - foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires locking 'mu_'}} \ - // expected-warning {{reading variable 'c' requires locking 'foo.cell_mu_'}} + foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \ + // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}} + foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \ + // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}} - foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_'}} \ - // expected-warning {{writing variable 'c' requires locking 'foop->cell_mu_' exclusively}} - foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}} \ - // expected-warning {{reading variable 'c' requires locking 'foop->cell_mu_'}} + foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \ + // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}} + foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \ + // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}} - (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_'}} \ - // expected-warning {{writing variable 'c' requires locking 'foop->cell_mu_' exclusively}} - (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}} \ - // expected-warning {{reading variable 'c' requires locking 'foop->cell_mu_'}} + (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \ + // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}} + (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \ + // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}} }; }; @@ -3917,34 +3938,34 @@ public: void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} mu2_.Lock(); mu2_.Unlock(); - } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} + } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} mu2_.Lock(); mu2_.Unlock(); - } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} + } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} mu2_.Lock(); mu2_.Unlock(); - } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + } // expected-warning {{mutex 'mu_' is still held at the end of function}} // Check locking the wrong thing. void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} mu2_.Lock(); // expected-note {{mutex acquired here}} - } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} \ - // expected-warning {{mutex 'mu2_' is still locked at the end of function}} + } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \ + // expected-warning {{mutex 'mu2_' is still held at the end of function}} void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} mu2_.ReaderLock(); // expected-note {{mutex acquired here}} - } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} \ - // expected-warning {{mutex 'mu2_' is still locked at the end of function}} + } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \ + // expected-warning {{mutex 'mu2_' is still held at the end of function}} void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} - mu2_.Unlock(); // expected-warning {{unlocking 'mu2_' that was not locked}} - } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}} + } // expected-warning {{mutex 'mu_' is still held at the end of function}} private: Mutex mu_; @@ -3971,7 +3992,7 @@ public: void test2() { mu_.AssertReaderHeld(); int b = a; - a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} } void test3() { @@ -4032,7 +4053,7 @@ public: else { mu_.Lock(); // expected-note {{mutex acquired here}} } - } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + } // expected-warning {{mutex 'mu_' is still held at the end of function}} void test10() { if (c) { @@ -4041,7 +4062,7 @@ public: else { mu_.AssertHeld(); } - } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + } // expected-warning {{mutex 'mu_' is still held at the end of function}} void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_); @@ -4178,52 +4199,52 @@ class PtGuardedBySanityTest { void test2() { mu1.ReaderLock(); - if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires locking 'mu2'}} - *a = 0; // expected-warning {{writing the value pointed to by 'a' requires locking 'mu2' exclusively}} + if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}} + *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}} - if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} - c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}} + c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}} - if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} - (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}} + (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}} - if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires locking 'mu2'}} - a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires locking 'mu2' exclusively}} - if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} - c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}} + a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}} + if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}} + c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}} mu1.Unlock(); } void test3() { mu2.Lock(); - if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires locking 'mu1'}} - *a = 0; // expected-warning {{reading variable 'a' requires locking 'mu1'}} + if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}} + *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}} - if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} - c->a = 0; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}} + c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}} - if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} - (*c).a = 0; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}} + (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}} - if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires locking 'mu1'}} - a[0] = 57; // expected-warning {{reading variable 'a' requires locking 'mu1'}} - if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} - c[0].a = 57; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}} + a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}} + if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}} + c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}} mu2.Unlock(); } void test4() { // Literal arrays - if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires locking 'mu1'}} - sa[0] = 57; // expected-warning {{writing variable 'sa' requires locking 'mu1' exclusively}} - if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires locking 'mu1'}} - sc[0].a = 57; // expected-warning {{writing variable 'sc' requires locking 'mu1' exclusively}} + if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}} + sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}} + if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}} + sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}} - if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires locking 'mu1'}} - *sa = 57; // expected-warning {{writing variable 'sa' requires locking 'mu1' exclusively}} - if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires locking 'mu1'}} - (*sc).a = 57; // expected-warning {{writing variable 'sc' requires locking 'mu1' exclusively}} - if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires locking 'mu1'}} - sc->a = 57; // expected-warning {{writing variable 'sc' requires locking 'mu1' exclusively}} + if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}} + *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}} + if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}} + (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}} + if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}} + sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}} } void test5() { @@ -4268,15 +4289,15 @@ class SmartPtr_PtGuardedBy_Test { void test2() { mu2.Lock(); - sp.get(); // expected-warning {{reading variable 'sp' requires locking 'mu1'}} - if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires locking 'mu1'}} - *sp = 0; // expected-warning {{reading variable 'sp' requires locking 'mu1'}} - sq->a = 0; // expected-warning {{reading variable 'sq' requires locking 'mu1'}} + sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}} + if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}} + *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}} + sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}} - if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires locking 'mu1'}} - sp[0] = 0; // expected-warning {{reading variable 'sp' requires locking 'mu1'}} - if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires locking 'mu1'}} - sq[0].a = 0; // expected-warning {{reading variable 'sq' requires locking 'mu1'}} + if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}} + sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}} + if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}} + sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}} mu2.Unlock(); } @@ -4285,14 +4306,14 @@ class SmartPtr_PtGuardedBy_Test { mu1.Lock(); sp.get(); - if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} - *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} - sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} + if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}} + *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}} + sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}} - if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} - sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} - if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} - sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} + if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}} + sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}} + if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}} + sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}} mu1.Unlock(); } @@ -4305,7 +4326,7 @@ namespace NonMemberCalleeICETest { class A { void Run() { - (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires exclusive lock on 'M'}} + (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}} } void RunHelper() __attribute__((exclusive_locks_required(M))); @@ -4314,3 +4335,46 @@ class A { } // end namespace NonMemberCalleeICETest + +namespace pt_guard_attribute_type { + int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}} + int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} + + void test() { + int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} + int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} + + typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}} + typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}} + } +} // end namespace pt_guard_attribute_type + + +namespace ThreadAttributesOnLambdas { + +class Foo { + Mutex mu_; + + void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_); + + void test() { + auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) { + LockedFunction(); + }; + + auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS { + LockedFunction(); + }; + + auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) { + mu_.Lock(); + }; + + func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}} + func2(); + func3(); + mu_.Unlock(); + } +}; + +} // end namespace ThreadAttributesOnLambdas diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index 1bd4e439b7b0a..6f9e7de4176de 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -109,26 +109,26 @@ int noanal_testfn(int y) NO_THREAD_SAFETY_ANALYSIS; int noanal_testfn(int y) { int x NO_THREAD_SAFETY_ANALYSIS = y; // \ - // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} return x; }; int noanal_test_var NO_THREAD_SAFETY_ANALYSIS; // \ - // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} class NoanalFoo { private: int test_field NO_THREAD_SAFETY_ANALYSIS; // \ - // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} void test_method() NO_THREAD_SAFETY_ANALYSIS; }; class NO_THREAD_SAFETY_ANALYSIS NoanalTestClass { // \ - // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} }; void noanal_fun_params(int lvar NO_THREAD_SAFETY_ANALYSIS); // \ - // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} //-----------------------------------------// @@ -229,28 +229,28 @@ class __attribute__((lockable (1))) LTestClass_args { // \ }; void l_test_function() LOCKABLE; // \ - // expected-warning {{'lockable' attribute only applies to classes}} + // expected-warning {{'lockable' attribute only applies to struct, union or class}} int l_testfn(int y) { int x LOCKABLE = y; // \ - // expected-warning {{'lockable' attribute only applies to classes}} + // expected-warning {{'lockable' attribute only applies to struct, union or class}} return x; } int l_test_var LOCKABLE; // \ - // expected-warning {{'lockable' attribute only applies to classes}} + // expected-warning {{'lockable' attribute only applies to struct, union or class}} class LFoo { private: int test_field LOCKABLE; // \ - // expected-warning {{'lockable' attribute only applies to classes}} + // expected-warning {{'lockable' attribute only applies to struct, union or class}} void test_method() LOCKABLE; // \ - // expected-warning {{'lockable' attribute only applies to classes}} + // expected-warning {{'lockable' attribute only applies to struct, union or class}} }; void l_function_params(int lvar LOCKABLE); // \ - // expected-warning {{'lockable' attribute only applies to classes}} + // expected-warning {{'lockable' attribute only applies to struct, union or class}} //-----------------------------------------// @@ -269,28 +269,28 @@ class __attribute__((scoped_lockable (1))) SLTestClass_args { // \ }; void sl_test_function() SCOPED_LOCKABLE; // \ - // expected-warning {{'scoped_lockable' attribute only applies to classes}} + // expected-warning {{'scoped_lockable' attribute only applies to struct, union or class}} int sl_testfn(int y) { int x SCOPED_LOCKABLE = y; // \ - // expected-warning {{'scoped_lockable' attribute only applies to classes}} + // expected-warning {{'scoped_lockable' attribute only applies to struct, union or class}} return x; } int sl_test_var SCOPED_LOCKABLE; // \ - // expected-warning {{'scoped_lockable' attribute only applies to classes}} + // expected-warning {{'scoped_lockable' attribute only applies to struct, union or class}} class SLFoo { private: int test_field SCOPED_LOCKABLE; // \ - // expected-warning {{'scoped_lockable' attribute only applies to classes}} + // expected-warning {{'scoped_lockable' attribute only applies to struct, union or class}} void test_method() SCOPED_LOCKABLE; // \ - // expected-warning {{'scoped_lockable' attribute only applies to classes}} + // expected-warning {{'scoped_lockable' attribute only applies to struct, union or class}} }; void sl_function_params(int lvar SCOPED_LOCKABLE); // \ - // expected-warning {{'scoped_lockable' attribute only applies to classes}} + // expected-warning {{'scoped_lockable' attribute only applies to struct, union or class}} //-----------------------------------------// @@ -353,13 +353,13 @@ int gb_var_arg_8 GUARDED_BY(muPointer); // illegal attribute arguments 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'}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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 **'}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is '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'}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'UnlockableMu'}} //3. // Thread Safety analysis tests @@ -424,13 +424,13 @@ int * pgb_var_arg_8 PT_GUARDED_BY(muPointer); // illegal attribute arguments 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}} + // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} 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}} + // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute}} //-----------------------------------------// @@ -446,12 +446,12 @@ int * pgb_var_arg_bad_4 PT_GUARDED_BY(umu); // \ Mutex mu_aa ACQUIRED_AFTER(mu1); Mutex aa_var_noargs __attribute__((acquired_after)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'acquired_after' attribute takes at least 1 argument}} class AAFoo { private: Mutex aa_field_noargs __attribute__((acquired_after)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'acquired_after' attribute takes at least 1 argument}} Mutex aa_field_args ACQUIRED_AFTER(mu1); }; @@ -485,15 +485,15 @@ Mutex aa_var_arg_8 ACQUIRED_AFTER(muPointer); // illegal attribute arguments 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}} + // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} Mutex aa_var_arg_bad_4 ACQUIRED_AFTER(umu); // \ - // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute}} 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}} + // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'capability("mutex")' attribute}} //-----------------------------------------// // Acquired Before (ab) @@ -506,12 +506,12 @@ UnlockableMu aa_var_arg_bad_5 ACQUIRED_AFTER(mu_aa); // \ Mutex mu_ab ACQUIRED_BEFORE(mu1); Mutex ab_var_noargs __attribute__((acquired_before)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'acquired_before' attribute takes at least 1 argument}} class ABFoo { private: Mutex ab_field_noargs __attribute__((acquired_before)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'acquired_before' attribute takes at least 1 argument}} Mutex ab_field_args ACQUIRED_BEFORE(mu1); }; @@ -548,15 +548,15 @@ Mutex ab_var_arg_8 ACQUIRED_BEFORE(muPointer); // illegal attribute arguments 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}} + // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} Mutex ab_var_arg_bad_4 ACQUIRED_BEFORE(umu); // \ - // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute}} 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}} + // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'capability("mutex")' attribute}} //-----------------------------------------// @@ -577,26 +577,26 @@ int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); int elf_testfn(int y) { int x EXCLUSIVE_LOCK_FUNCTION() = y; // \ - // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} return x; }; int elf_test_var EXCLUSIVE_LOCK_FUNCTION(); // \ - // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} class ElfFoo { private: int test_field EXCLUSIVE_LOCK_FUNCTION(); // \ - // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} void test_method() EXCLUSIVE_LOCK_FUNCTION(); }; class EXCLUSIVE_LOCK_FUNCTION() ElfTestClass { // \ - // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} }; void elf_fun_params(int lvar EXCLUSIVE_LOCK_FUNCTION()); // \ - // expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} // Check argument parsing. @@ -617,9 +617,9 @@ int elf_function_9(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(1,2); 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}} + // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int elf_function_bad_4() EXCLUSIVE_LOCK_FUNCTION(umu); // \ - // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} 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}} @@ -649,25 +649,25 @@ int slf_testfn(int y) SHARED_LOCK_FUNCTION(); int slf_testfn(int y) { int x SHARED_LOCK_FUNCTION() = y; // \ - // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_lock_function' attribute only applies to functions}} return x; }; int slf_test_var SHARED_LOCK_FUNCTION(); // \ - // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_lock_function' attribute only applies to functions}} void slf_fun_params(int lvar SHARED_LOCK_FUNCTION()); // \ - // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_lock_function' attribute only applies to functions}} class SlfFoo { private: int test_field SHARED_LOCK_FUNCTION(); // \ - // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_lock_function' attribute only applies to functions}} void test_method() SHARED_LOCK_FUNCTION(); }; class SHARED_LOCK_FUNCTION() SlfTestClass { // \ - // expected-warning {{'shared_lock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_lock_function' attribute only applies to functions}} }; // Check argument parsing. @@ -689,9 +689,9 @@ int slf_function_9(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(1,2); 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}} + // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int slf_function_bad_4() SHARED_LOCK_FUNCTION(umu); // \ - // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} 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}} @@ -715,7 +715,7 @@ int slf_function_bad_7() SHARED_LOCK_FUNCTION(0); // \ // plus an optional list of locks (vars/fields) void etf_function() __attribute__((exclusive_trylock_function)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'exclusive_trylock_function' attribute takes at least 1 argument}} void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2); @@ -725,26 +725,26 @@ int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); int etf_testfn(int y) { int x EXCLUSIVE_TRYLOCK_FUNCTION(1) = y; // \ - // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} return x; }; int etf_test_var EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ - // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} class EtfFoo { private: int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ - // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); }; class EXCLUSIVE_TRYLOCK_FUNCTION(1) EtfTestClass { // \ - // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} }; void etf_fun_params(int lvar EXCLUSIVE_TRYLOCK_FUNCTION(1)); // \ - // expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} // Check argument parsing. @@ -771,9 +771,9 @@ int etf_function_bad_3() EXCLUSIVE_TRYLOCK_FUNCTION(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}} + // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} 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}} + // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} //-----------------------------------------// @@ -788,7 +788,7 @@ int etf_function_bad_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, umu); // \ // plus an optional list of locks (vars/fields) void stf_function() __attribute__((shared_trylock_function)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'shared_trylock_function' attribute takes at least 1 argument}} void stf_function_args() SHARED_TRYLOCK_FUNCTION(1, mu2); @@ -798,26 +798,26 @@ int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); int stf_testfn(int y) { int x SHARED_TRYLOCK_FUNCTION(1) = y; // \ - // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_trylock_function' attribute only applies to functions}} return x; }; int stf_test_var SHARED_TRYLOCK_FUNCTION(1); // \ - // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_trylock_function' attribute only applies to functions}} void stf_fun_params(int lvar SHARED_TRYLOCK_FUNCTION(1)); // \ - // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_trylock_function' attribute only applies to functions}} class StfFoo { private: int test_field SHARED_TRYLOCK_FUNCTION(1); // \ - // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_trylock_function' attribute only applies to functions}} void test_method() SHARED_TRYLOCK_FUNCTION(1); }; class SHARED_TRYLOCK_FUNCTION(1) StfTestClass { // \ - // expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}} + // expected-warning {{'shared_trylock_function' attribute only applies to functions}} }; // Check argument parsing. @@ -845,9 +845,9 @@ int stf_function_bad_3() SHARED_TRYLOCK_FUNCTION(muDoublePointer); // \ 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}} + // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} 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}} + // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} //-----------------------------------------// @@ -868,26 +868,26 @@ int uf_testfn(int y) UNLOCK_FUNCTION(); int uf_testfn(int y) { int x UNLOCK_FUNCTION() = y; // \ - // expected-warning {{'unlock_function' attribute only applies to functions and methods}} + // expected-warning {{'unlock_function' attribute only applies to functions}} return x; }; int uf_test_var UNLOCK_FUNCTION(); // \ - // expected-warning {{'unlock_function' attribute only applies to functions and methods}} + // expected-warning {{'unlock_function' attribute only applies to functions}} class UfFoo { private: int test_field UNLOCK_FUNCTION(); // \ - // expected-warning {{'unlock_function' attribute only applies to functions and methods}} + // expected-warning {{'unlock_function' attribute only applies to functions}} void test_method() UNLOCK_FUNCTION(); }; class NO_THREAD_SAFETY_ANALYSIS UfTestClass { // \ - // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}} + // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} }; void uf_fun_params(int lvar UNLOCK_FUNCTION()); // \ - // expected-warning {{'unlock_function' attribute only applies to functions and methods}} + // expected-warning {{'unlock_function' attribute only applies to functions}} // Check argument parsing. @@ -908,9 +908,9 @@ int uf_function_9(Mutex x, Mutex y) UNLOCK_FUNCTION(1,2); 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}} + // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int uf_function_bad_4() UNLOCK_FUNCTION(umu); // \ - // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} int uf_function_bad_1() UNLOCK_FUNCTION(1); // \ // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -944,25 +944,25 @@ int lr_testfn(int y) LOCK_RETURNED(mu1); int lr_testfn(int y) { int x LOCK_RETURNED(mu1) = y; // \ - // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + // expected-warning {{'lock_returned' attribute only applies to functions}} return x; }; int lr_test_var LOCK_RETURNED(mu1); // \ - // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + // expected-warning {{'lock_returned' attribute only applies to functions}} void lr_fun_params(int lvar LOCK_RETURNED(mu1)); // \ - // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + // expected-warning {{'lock_returned' attribute only applies to functions}} class LrFoo { private: int test_field LOCK_RETURNED(mu1); // \ - // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + // expected-warning {{'lock_returned' attribute only applies to functions}} void test_method() LOCK_RETURNED(mu1); }; class LOCK_RETURNED(mu1) LrTestClass { // \ - // expected-warning {{'lock_returned' attribute only applies to functions and methods}} + // expected-warning {{'lock_returned' attribute only applies to functions}} }; // Check argument parsing. @@ -980,13 +980,13 @@ int lr_function_8() LOCK_RETURNED(muPointer); // illegal attribute arguments int lr_function_bad_1() LOCK_RETURNED(1); // \ - // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int lr_function_bad_4() LOCK_RETURNED(umu); // \ - // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -1001,7 +1001,7 @@ int lr_function_bad_4() LOCK_RETURNED(umu); // \ // takes one or more arguments, all locks (vars/fields) void le_function() __attribute__((locks_excluded)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'locks_excluded' attribute takes at least 1 argument}} void le_function_arg() LOCKS_EXCLUDED(mu1); @@ -1011,25 +1011,25 @@ int le_testfn(int y) LOCKS_EXCLUDED(mu1); int le_testfn(int y) { int x LOCKS_EXCLUDED(mu1) = y; // \ - // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + // expected-warning {{'locks_excluded' attribute only applies to functions}} return x; }; int le_test_var LOCKS_EXCLUDED(mu1); // \ - // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + // expected-warning {{'locks_excluded' attribute only applies to functions}} void le_fun_params(int lvar LOCKS_EXCLUDED(mu1)); // \ - // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + // expected-warning {{'locks_excluded' attribute only applies to functions}} class LeFoo { private: int test_field LOCKS_EXCLUDED(mu1); // \ - // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + // expected-warning {{'locks_excluded' attribute only applies to functions}} void test_method() LOCKS_EXCLUDED(mu1); }; class LOCKS_EXCLUDED(mu1) LeTestClass { // \ - // expected-warning {{'locks_excluded' attribute only applies to functions and methods}} + // expected-warning {{'locks_excluded' attribute only applies to functions}} }; // Check argument parsing. @@ -1047,13 +1047,13 @@ int le_function_8() LOCKS_EXCLUDED(muPointer); // illegal attribute arguments int le_function_bad_1() LOCKS_EXCLUDED(1); // \ - // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int le_function_bad_4() LOCKS_EXCLUDED(umu); // \ - // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -1068,7 +1068,7 @@ int le_function_bad_4() LOCKS_EXCLUDED(umu); // \ // takes one or more arguments, all locks (vars/fields) void elr_function() __attribute__((exclusive_locks_required)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'exclusive_locks_required' attribute takes at least 1 argument}} void elr_function_arg() EXCLUSIVE_LOCKS_REQUIRED(mu1); @@ -1078,25 +1078,25 @@ int elr_testfn(int y) EXCLUSIVE_LOCKS_REQUIRED(mu1); int elr_testfn(int y) { int x EXCLUSIVE_LOCKS_REQUIRED(mu1) = y; // \ - // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} return x; }; int elr_test_var EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ - // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} void elr_fun_params(int lvar EXCLUSIVE_LOCKS_REQUIRED(mu1)); // \ - // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} class ElrFoo { private: int test_field EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ - // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} void test_method() EXCLUSIVE_LOCKS_REQUIRED(mu1); }; class EXCLUSIVE_LOCKS_REQUIRED(mu1) ElrTestClass { // \ - // expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} }; // Check argument parsing. @@ -1114,13 +1114,13 @@ int elr_function_8() EXCLUSIVE_LOCKS_REQUIRED(muPointer); // illegal attribute arguments 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}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int elr_function_bad_4() EXCLUSIVE_LOCKS_REQUIRED(umu); // \ - // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute}} @@ -1136,7 +1136,7 @@ int elr_function_bad_4() EXCLUSIVE_LOCKS_REQUIRED(umu); // \ // takes one or more arguments, all locks (vars/fields) void slr_function() __attribute__((shared_locks_required)); // \ - // expected-error {{attribute takes at least 1 argument}} + // expected-error {{'shared_locks_required' attribute takes at least 1 argument}} void slr_function_arg() SHARED_LOCKS_REQUIRED(mu1); @@ -1146,25 +1146,25 @@ int slr_testfn(int y) SHARED_LOCKS_REQUIRED(mu1); int slr_testfn(int y) { int x SHARED_LOCKS_REQUIRED(mu1) = y; // \ - // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'shared_locks_required' attribute only applies to functions}} return x; }; int slr_test_var SHARED_LOCKS_REQUIRED(mu1); // \ - // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'shared_locks_required' attribute only applies to functions}} void slr_fun_params(int lvar SHARED_LOCKS_REQUIRED(mu1)); // \ - // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'shared_locks_required' attribute only applies to functions}} class SlrFoo { private: int test_field SHARED_LOCKS_REQUIRED(mu1); // \ - // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'shared_locks_required' attribute only applies to functions}} void test_method() SHARED_LOCKS_REQUIRED(mu1); }; class SHARED_LOCKS_REQUIRED(mu1) SlrTestClass { // \ - // expected-warning {{'shared_locks_required' attribute only applies to functions and methods}} + // expected-warning {{'shared_locks_required' attribute only applies to functions}} }; // Check argument parsing. @@ -1182,13 +1182,13 @@ int slr_function_8() SHARED_LOCKS_REQUIRED(muPointer); // illegal attribute arguments 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}} + // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} 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}} + // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} int slr_function_bad_4() SHARED_LOCKS_REQUIRED(umu); // \ - // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute}} //-----------------------------------------// @@ -1430,7 +1430,7 @@ class Foo { 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'}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'InheritanceTest::Derived3'}} void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1_, mu2_) { a = 0; diff --git a/test/SemaCXX/warn-undefined-bool-conversion.cpp b/test/SemaCXX/warn-undefined-bool-conversion.cpp new file mode 100644 index 0000000000000..1f8baa0e8d8ab --- /dev/null +++ b/test/SemaCXX/warn-undefined-bool-conversion.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wundefined-bool-conversion %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-bool-conversion -Wundefined-bool-conversion %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wbool-conversion %s + +void test1(int &x) { + if (x == 1) { } + if (&x) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + if (!&x) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} +} + +class test2 { + test2() : x(y) {} + + void foo() { + if (this) { } + // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true}} + + if (!this) { } + // expected-warning@-1{{'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true}} + } + + void bar() { + if (x == 1) { } + if (&x) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + if (!&x) { } + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + } + + int &x; + int y; +}; + +namespace function_return_reference { + int& get_int(); + // expected-note@-1 3{{'get_int' returns a reference}} + class B { + public: + static int &stat(); + // expected-note@-1 3{{'stat' returns a reference}} + int &get(); + // expected-note@-1 6{{'get' returns a reference}} + }; + + void test() { + if (&get_int()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (&(get_int())) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (!&get_int()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + if (&B::stat()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (&(B::stat())) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (!&B::stat()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + B b; + if (&b.get()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (&(b.get())) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (!&b.get()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + B* b_ptr = &b; + if (&b_ptr->get()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (&(b_ptr->get())) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (!&b_ptr->get()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + int& (B::*m_ptr)() = &B::get; + if (&(b.*m_ptr)()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (&((b.*m_ptr)())) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (!&(b.*m_ptr)()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + + int& (*f_ptr)() = &get_int; + if (&(*f_ptr)()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (&((*f_ptr)())) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + if (!&(*f_ptr)()) {} + // expected-warning@-1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}} + } +} diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index dd071258e29d1..b08467ab51e63 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -Wunreachable-code -Wno-unused-value +// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -std=c++11 -Wunreachable-code-aggressive -Wno-unused-value -Wno-tautological-compare int &halt() __attribute__((noreturn)); int &live(); @@ -107,3 +107,303 @@ template <> void funcToSpecialize<int>() { dead(); // expected-warning {{will never be executed}} } +// Handle 'try' code dominating a dead return. +enum PR19040_test_return_t +{ PR19040_TEST_FAILURE }; +namespace PR19040_libtest +{ + class A { + public: + ~A (); + }; +} +PR19040_test_return_t PR19040_fn1 () +{ + try + { + throw PR19040_libtest::A (); + } catch (...) + { + return PR19040_TEST_FAILURE; + } + return PR19040_TEST_FAILURE; // expected-warning {{will never be executed}} +} + +__attribute__((noreturn)) +void raze(); + +namespace std { +template<typename T> struct basic_string { + basic_string(const T* x) {} + ~basic_string() {}; +}; +typedef basic_string<char> string; +} + +std::string testStr() { + raze(); + return ""; // expected-warning {{'return' will never be executed}} +} + +std::string testStrWarn(const char *s) { + raze(); + return s; // expected-warning {{will never be executed}} +} + +bool testBool() { + raze(); + return true; // expected-warning {{'return' will never be executed}} +} + +static const bool ConditionVar = 1; +int test_global_as_conditionVariable() { + if (ConditionVar) + return 1; + return 0; // no-warning +} + +// Handle unreachable temporary destructors. +class A { +public: + A(); + ~A(); +}; + +__attribute__((noreturn)) +void raze(const A& x); + +void test_with_unreachable_tmp_dtors(int x) { + raze(x ? A() : A()); // no-warning +} + +// Test sizeof - sizeof in enum declaration. +enum { BrownCow = sizeof(long) - sizeof(char) }; +enum { CowBrown = 8 - 1 }; + + +int test_enum_sizeof_arithmetic() { + if (BrownCow) + return 1; + return 2; +} + +int test_enum_arithmetic() { + if (CowBrown) + return 1; + return 2; // expected-warning {{never be executed}} +} + +int test_arithmetic() { + if (8 -1) + return 1; + return 2; // expected-warning {{never be executed}} +} + +int test_treat_const_bool_local_as_config_value() { + const bool controlValue = false; + if (!controlValue) + return 1; + test_treat_const_bool_local_as_config_value(); // no-warning + return 0; +} + +int test_treat_non_const_bool_local_as_non_config_value() { + bool controlValue = false; + if (!controlValue) + return 1; + // There is no warning here because 'controlValue' isn't really + // a control value at all. The CFG will not treat this + // branch as unreachable. + test_treat_non_const_bool_local_as_non_config_value(); // no-warning + return 0; +} + +void test_do_while(int x) { + // Handle trivial expressions with + // implicit casts to bool. + do { + break; + } while (0); // no-warning +} + +class Frobozz { +public: + Frobozz(int x); + ~Frobozz(); +}; + +Frobozz test_return_object(int flag) { + return Frobozz(flag); + return Frobozz(42); // expected-warning {{'return' will never be executed}} +} + +Frobozz test_return_object_control_flow(int flag) { + return Frobozz(flag); + return Frobozz(flag ? 42 : 24); // expected-warning {{code will never be executed}} +} + +void somethingToCall(); + +static constexpr bool isConstExprConfigValue() { return true; } + +int test_const_expr_config_value() { + if (isConstExprConfigValue()) { + somethingToCall(); + return 0; + } + somethingToCall(); // no-warning + return 1; +} +int test_const_expr_config_value_2() { + if (!isConstExprConfigValue()) { + somethingToCall(); // no-warning + return 0; + } + somethingToCall(); + return 1; +} + +class Frodo { +public: + static const bool aHobbit = true; +}; + +void test_static_class_var() { + if (Frodo::aHobbit) + somethingToCall(); + else + somethingToCall(); // no-warning +} + +void test_static_class_var(Frodo &F) { + if (F.aHobbit) + somethingToCall(); + else + somethingToCall(); // no-warning +} + +void test_unreachable_for_null_increment() { + for (unsigned i = 0; i < 10 ; ) // no-warning + break; +} + +void test_unreachable_forrange_increment() { + int x[10] = { 0 }; + for (auto i : x) { // expected-warning {{loop will run at most once (loop increment never executed)}} + break; + } +} + +void calledFun() {} + +// Test "silencing" with parentheses. +void test_with_paren_silencing(int x) { + if (false) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}} + if ((false)) calledFun(); // no-warning + + if (true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + + if ((true)) + calledFun(); + else + calledFun(); // no-warning + + if (!true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + calledFun(); // expected-warning {{code will never be executed}} + else + calledFun(); + + if ((!true)) + calledFun(); // no-warning + else + calledFun(); + + if (!(true)) + calledFun(); // no-warning + else + calledFun(); +} + +void test_with_paren_silencing_impcast(int x) { + if (0) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}} + if ((0)) calledFun(); // no-warning + + if (1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + + if ((1)) + calledFun(); + else + calledFun(); // no-warning + + if (!1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} + calledFun(); // expected-warning {{code will never be executed}} + else + calledFun(); + + if ((!1)) + calledFun(); // no-warning + else + calledFun(); + + if (!(1)) + calledFun(); // no-warning + else + calledFun(); +} + +void tautological_compare(bool x, int y) { + if (x > 10) // expected-note {{silence}} + calledFun(); // expected-warning {{will never be executed}} + if (10 < x) // expected-note {{silence}} + calledFun(); // expected-warning {{will never be executed}} + if (x == 10) // expected-note {{silence}} + calledFun(); // expected-warning {{will never be executed}} + + if (x < 10) // expected-note {{silence}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + if (10 > x) // expected-note {{silence}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + if (x != 10) // expected-note {{silence}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + + if (y != 5 && y == 5) // expected-note {{silence}} + calledFun(); // expected-warning {{will never be executed}} + + if (y > 5 && y < 4) // expected-note {{silence}} + calledFun(); // expected-warning {{will never be executed}} + + if (y < 10 || y > 5) // expected-note {{silence}} + calledFun(); + else + calledFun(); // expected-warning {{will never be executed}} + + // TODO: Extend warning to the following code: + if (x < -1) + calledFun(); + if (x == -1) + calledFun(); + + if (x != -1) + calledFun(); + else + calledFun(); + if (-1 > x) + calledFun(); + else + calledFun(); + + if (y == -1 && y != -1) + calledFun(); +} diff --git a/test/SemaCXX/warn-unused-attribute.cpp b/test/SemaCXX/warn-unused-attribute.cpp index 72f96eea0b319..f52de3b931b0c 100644 --- a/test/SemaCXX/warn-unused-attribute.cpp +++ b/test/SemaCXX/warn-unused-attribute.cpp @@ -1,20 +1,20 @@ // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s -struct __attribute__((warn_unused)) Test -{ - Test(); - ~Test(); - void use(); +struct __attribute__((warn_unused)) Test { + Test(); + ~Test(); + void use(); }; -struct TestNormal -{ - TestNormal(); +struct TestNormal { + TestNormal(); }; -int main() -{ - Test unused; // expected-warning {{unused variable 'unused'}} - Test used; - TestNormal normal; - used.use(); +int main(void) { + Test unused; // expected-warning {{unused variable 'unused'}} + Test used; + TestNormal normal; + used.use(); + + int i __attribute__((warn_unused)) = 12; // expected-warning {{'warn_unused' attribute only applies to struct, union or class}} + return i; } diff --git a/test/SemaCXX/warn-unused-comparison.cpp b/test/SemaCXX/warn-unused-comparison.cpp index 0153f213ba1fc..3afad585b6689 100644 --- a/test/SemaCXX/warn-unused-comparison.cpp +++ b/test/SemaCXX/warn-unused-comparison.cpp @@ -3,6 +3,10 @@ struct A { bool operator==(const A&); bool operator!=(const A&); + bool operator<(const A&); + bool operator>(const A&); + bool operator<=(const A&); + bool operator>=(const A&); A operator|=(const A&); operator bool(); }; @@ -15,6 +19,11 @@ void test() { // expected-note {{use '=' to turn this equality comparison into an assignment}} x != 7; // expected-warning {{inequality comparison result unused}} \ // expected-note {{use '|=' to turn this inequality comparison into an or-assignment}} + x < 7; // expected-warning {{relational comparison result unused}} + x > 7; // expected-warning {{relational comparison result unused}} + x <= 7; // expected-warning {{relational comparison result unused}} + x >= 7; // expected-warning {{relational comparison result unused}} + 7 == x; // expected-warning {{equality comparison result unused}} p == p; // expected-warning {{equality comparison result unused}} \ // expected-note {{use '=' to turn this equality comparison into an assignment}} \ @@ -25,6 +34,11 @@ void test() { // expected-note {{use '=' to turn this equality comparison into an assignment}} a != b; // expected-warning {{inequality comparison result unused}} \ // expected-note {{use '|=' to turn this inequality comparison into an or-assignment}} + a < b; // expected-warning {{relational comparison result unused}} + a > b; // expected-warning {{relational comparison result unused}} + a <= b; // expected-warning {{relational comparison result unused}} + a >= b; // expected-warning {{relational comparison result unused}} + A() == b; // expected-warning {{equality comparison result unused}} if (42) x == 7; // expected-warning {{equality comparison result unused}} \ // expected-note {{use '=' to turn this equality comparison into an assignment}} @@ -92,3 +106,30 @@ namespace PR10291 { X<int> x; } + +namespace PR19724 { +class stream { +} cout, cin; + +stream &operator<(stream &s, int); +bool operator<(stream &s, stream &s2); + +void test() { + cout < 5; // no warning, operator returns a reference + cout < cin; // expected-warning {{relational comparison result unused}} +} +} + +namespace PR19791 { +struct S { + void operator!=(int); + int operator==(int); +}; + +void test() { + S s; + s != 1; + s == 1; // expected-warning{{equality comparison result unused}} + // expected-note@-1{{use '=' to turn this equality comparison into an assignment}} +} +} diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp index b0af5b3322706..df4c47e71787d 100644 --- a/test/SemaCXX/warn-unused-filescoped.cpp +++ b/test/SemaCXX/warn-unused-filescoped.cpp @@ -32,6 +32,13 @@ namespace test7 inline void bar(int, int) { } }; +namespace pr19713 { +#if __cplusplus >= 201103L + static constexpr int constexpr1() { return 1; } + constexpr int constexpr2() { return 2; } +#endif +} + #else #define HEADER #include "warn-unused-filescoped.cpp" @@ -193,4 +200,12 @@ void bar() { void func() __attribute__((used)); } static void func() {} } +namespace pr19713 { +#if __cplusplus >= 201103L + // FIXME: We should warn on both of these. + static constexpr int constexpr3() { return 1; } // expected-warning {{unused}} + constexpr int constexpr4() { return 2; } +#endif +} + #endif diff --git a/test/SemaCXX/warn-unused-label-error.cpp b/test/SemaCXX/warn-unused-label-error.cpp new file mode 100644 index 0000000000000..66b616f3cf284 --- /dev/null +++ b/test/SemaCXX/warn-unused-label-error.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -verify %s + +static int unused_local_static; + +namespace PR8455 { + void f() { + A: // expected-warning {{unused label 'A'}} + __attribute__((unused)) int i; // attribute applies to variable + B: // attribute applies to label + __attribute__((unused)); int j; // expected-warning {{unused variable 'j'}} + } + + void g() { + C: // unused label 'C' will not appear here because an error has occurred + __attribute__((unused)) + #pragma weak unused_local_static // expected-error {{expected ';' after __attribute__}} + ; + } + + void h() { + D: // expected-warning {{unused label 'D'}} + #pragma weak unused_local_static + __attribute__((unused)) // expected-warning {{declaration does not declare anything}} + ; + } +} diff --git a/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp index 5e43d3ec04222..4e1347cc307a5 100644 --- a/test/SemaCXX/warn-unused-value.cpp +++ b/test/SemaCXX/warn-unused-value.cpp @@ -32,7 +32,7 @@ void b(Foo f1, Foo f2) { } namespace test2 { - extern "C" { + extern "C++" { namespace std { template<typename T> struct basic_string { struct X {}; diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 93d2f6f9563b6..8dcbe7271d69d 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s template<typename T> void f() { T t; t = 17; @@ -115,6 +115,28 @@ namespace PR11550 { } } +namespace PR19305 { + template<typename T> int n = 0; // no warning + int a = n<int>; + + template<typename T> const int l = 0; // no warning + int b = l<int>; + + // PR19558 + template<typename T> const int o = 0; // no warning + template<typename T> const int o<T*> = 0; // no warning + int c = o<int*>; + + template<> int o<void> = 0; // no warning + int d = o<void>; + + // FIXME: It'd be nice to warn here. + template<typename T> int m = 0; + template<typename T> int m<T*> = 0; + + template<> const int m<void> = 0; // expected-warning {{unused variable}} +} + namespace ctor_with_cleanups { struct S1 { ~S1(); @@ -128,26 +150,3 @@ namespace ctor_with_cleanups { } #include "Inputs/warn-unused-variables.h" - -namespace PR8455 { - void f() { - A: // expected-warning {{unused label 'A'}} - __attribute__((unused)) int i; // attribute applies to variable - B: // attribute applies to label - __attribute__((unused)); int j; // expected-warning {{unused variable 'j'}} - } - - void g() { - C: // unused label 'C' will not appear here because an error occurs - __attribute__((unused)) - #pragma weak unused_local_static // expected-error {{expected ';' after __attribute__}} - ; - } - - void h() { - D: // expected-warning {{unused label 'D'}} - #pragma weak unused_local_static - __attribute__((unused)) // expected-warning {{declaration does not declare anything}} - ; - } -} diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp index 135e0342596c4..671ff297cfa15 100644 --- a/test/SemaCXX/warn-weak-vtables.cpp +++ b/test/SemaCXX/warn-weak-vtables.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables -Wweak-template-vtables +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple %itanium_abi_triple -Wweak-vtables -Wweak-template-vtables +// RUN: %clang_cc1 %s -fsyntax-only -triple %ms_abi_triple -Werror -Wno-weak-vtables -Wno-weak-template-vtables struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} virtual void f() { } diff --git a/test/SemaCXX/windows-arm-valist.cpp b/test/SemaCXX/windows-arm-valist.cpp new file mode 100644 index 0000000000000..d12be65e4f9f0 --- /dev/null +++ b/test/SemaCXX/windows-arm-valist.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple thumbv7--windows-msvc -std=c++11 -verify -fsyntax-only %s +// expected-no-diagnostics + +#include <stdarg.h> + +template <typename lhs_, typename rhs_> +struct is_same { enum { value = 0 }; }; + +template <typename type_> +struct is_same<type_, type_> { enum { value = 1 }; }; + +void check() { + va_list va; + char *cp; + static_assert(is_same<decltype(va), decltype(cp)>::value, + "type mismatch for va_list"); +} diff --git a/test/SemaCXX/writable-strings-deprecated.cpp b/test/SemaCXX/writable-strings-deprecated.cpp index b8f605b63d66a..f9258334980b8 100644 --- a/test/SemaCXX/writable-strings-deprecated.cpp +++ b/test/SemaCXX/writable-strings-deprecated.cpp @@ -1,14 +1,25 @@ // RUN: %clang_cc1 -fsyntax-only -Wno-deprecated-writable-strings -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wno-deprecated -Wdeprecated-increment-bool -verify %s // RUN: %clang_cc1 -fsyntax-only -fwritable-strings -verify %s // RUN: %clang_cc1 -fsyntax-only -Wno-write-strings -verify %s // RUN: %clang_cc1 -fsyntax-only -Werror=c++11-compat -verify %s -DERROR +// RUN: %clang_cc1 -fsyntax-only -Werror=deprecated -Wno-error=deprecated-increment-bool -verify %s -DERROR +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -Wno-deprecated -Wdeprecated-increment-bool +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -pedantic-errors -DERROR // rdar://8827606 char *fun(void) { return "foo"; +#if __cplusplus >= 201103L #ifdef ERROR - // expected-error@-2 {{deprecated}} + // expected-error@-3 {{ISO C++11 does not allow conversion from string literal to 'char *'}} +#else + // expected-warning@-5 {{ISO C++11 does not allow conversion from string literal to 'char *'}} +#endif +#elif defined(ERROR) + // expected-error@-8 {{deprecated}} #endif } |
