diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
commit | b35a2aa71f76a334a9c98c0a3c3995b5d902d2b9 (patch) | |
tree | cdff4a5d1a715d4ad622fd8f190128b54bebe440 /test/SemaCXX | |
parent | 3748d41833787fcbf59cc5624e8d2b042a8991bc (diff) | |
parent | 741e05796da92b46d4f7bcbee00702ff37df6489 (diff) |
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103upstream/google/stable
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaCXX')
66 files changed, 1721 insertions, 201 deletions
diff --git a/test/SemaCXX/Float16.cpp b/test/SemaCXX/Float16.cpp new file mode 100644 index 0000000000..f27c383985 --- /dev/null +++ b/test/SemaCXX/Float16.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE +// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE + +#ifdef HAVE +// expected-no-diagnostics +#endif // HAVE + +#ifndef HAVE +// expected-error@+2{{_Float16 is not supported on this target}} +#endif // !HAVE +_Float16 f; + +#ifndef HAVE +// expected-error@+2{{invalid suffix 'F16' on floating constant}} +#endif // !HAVE +const auto g = 1.1F16; diff --git a/test/SemaCXX/PR10177.cpp b/test/SemaCXX/PR10177.cpp index 59630be508..0d2e792f52 100644 --- a/test/SemaCXX/PR10177.cpp +++ b/test/SemaCXX/PR10177.cpp @@ -57,11 +57,10 @@ namespace N { } #else -// expected-no-diagnostics namespace { template<typename> extern int n; } template<typename T> int g() { return n<int>; } -namespace { extern template int n<int>; } +namespace { extern template int n<int>; } // expected-error {{explicit instantiation declaration of 'n<int>' with internal linkage}} #endif diff --git a/test/SemaCXX/PR40395.cpp b/test/SemaCXX/PR40395.cpp new file mode 100644 index 0000000000..469c86d562 --- /dev/null +++ b/test/SemaCXX/PR40395.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s +// expected-no-diagnostics + +// PR40395 - ConstantExpr shouldn't cause the template object to infinitely +// expand. +struct _GUID {}; +struct __declspec(uuid("{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}")) B {}; + +template <const _GUID* piid> +struct A { + virtual void baz() { A<piid>(); } +}; + +void f() { + A<&__uuidof(B)>(); +} diff --git a/test/SemaCXX/PR41139.cpp b/test/SemaCXX/PR41139.cpp new file mode 100644 index 0000000000..e120e42b8b --- /dev/null +++ b/test/SemaCXX/PR41139.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s + +// expected-no-diagnostics + +// This test should not crash. +int f1( unsigned ) { return 0; } + +template <class R, class... Args> +struct S1 { + S1( R(*f)(Args...) ) {} +}; + +int main() { + S1 s1( f1 ); +} diff --git a/test/SemaCXX/address-space-conversion.cpp b/test/SemaCXX/address-space-conversion.cpp index d21d419423..b1fb698163 100644 --- a/test/SemaCXX/address-space-conversion.cpp +++ b/test/SemaCXX/address-space-conversion.cpp @@ -131,24 +131,24 @@ void test_dynamic_cast(A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, void test_reinterpret_cast(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2, A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2, - const void __attribute__((address_space(1))) *cvp1) { - // reinterpret_cast can be used to cast to a different address space. - (void)reinterpret_cast<A_ptr>(ap1); - (void)reinterpret_cast<A_ptr>(ap2); + const void __attribute__((address_space(1))) * cvp1) { + // reinterpret_cast can't be used to cast to a different address space unless they are matching (i.e. overlapping). + (void)reinterpret_cast<A_ptr>(ap1); // expected-error{{reinterpret_cast from 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') to 'A_ptr' (aka 'A *') is not allowed}} + (void)reinterpret_cast<A_ptr>(ap2); // expected-error{{reinterpret_cast from 'A_ptr_2' (aka '__attribute__((address_space(2))) A *') to 'A_ptr' (aka 'A *') is not allowed}} (void)reinterpret_cast<A_ptr>(bp); - (void)reinterpret_cast<A_ptr>(bp1); - (void)reinterpret_cast<A_ptr>(bp2); + (void)reinterpret_cast<A_ptr>(bp1); // expected-error{{reinterpret_cast from 'B_ptr_1' (aka '__attribute__((address_space(1))) B *') to 'A_ptr' (aka 'A *') is not allowed}} + (void)reinterpret_cast<A_ptr>(bp2); // expected-error{{reinterpret_cast from 'B_ptr_2' (aka '__attribute__((address_space(2))) B *') to 'A_ptr' (aka 'A *') is not allowed}} (void)reinterpret_cast<A_ptr>(vp); - (void)reinterpret_cast<A_ptr>(vp1); - (void)reinterpret_cast<A_ptr>(vp2); - (void)reinterpret_cast<A_ptr_1>(ap); - (void)reinterpret_cast<A_ptr_1>(ap2); - (void)reinterpret_cast<A_ptr_1>(bp); + (void)reinterpret_cast<A_ptr>(vp1); // expected-error{{reinterpret_cast from 'void_ptr_1' (aka '__attribute__((address_space(1))) void *') to 'A_ptr' (aka 'A *') is not allowed}} + (void)reinterpret_cast<A_ptr>(vp2); // expected-error{{reinterpret_cast from 'void_ptr_2' (aka '__attribute__((address_space(2))) void *') to 'A_ptr' (aka 'A *') is not allowed}} + (void)reinterpret_cast<A_ptr_1>(ap); // expected-error{{reinterpret_cast from 'A_ptr' (aka 'A *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} + (void)reinterpret_cast<A_ptr_1>(ap2); // expected-error{{reinterpret_cast from 'A_ptr_2' (aka '__attribute__((address_space(2))) A *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} + (void)reinterpret_cast<A_ptr_1>(bp); // expected-error{{reinterpret_cast from 'B_ptr' (aka 'B *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} (void)reinterpret_cast<A_ptr_1>(bp1); - (void)reinterpret_cast<A_ptr_1>(bp2); - (void)reinterpret_cast<A_ptr_1>(vp); + (void)reinterpret_cast<A_ptr_1>(bp2); // expected-error{{reinterpret_cast from 'B_ptr_2' (aka '__attribute__((address_space(2))) B *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} + (void)reinterpret_cast<A_ptr_1>(vp); // expected-error{{reinterpret_cast from 'void_ptr' (aka 'void *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} (void)reinterpret_cast<A_ptr_1>(vp1); - (void)reinterpret_cast<A_ptr_1>(vp2); + (void)reinterpret_cast<A_ptr_1>(vp2); // expected-error{{reinterpret_cast from 'void_ptr_2' (aka '__attribute__((address_space(2))) void *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} // ... but don't try to cast away constness! (void)reinterpret_cast<A_ptr_2>(cvp1); // expected-error{{casts away qualifiers}} diff --git a/test/SemaCXX/adl.cpp b/test/SemaCXX/adl.cpp new file mode 100644 index 0000000000..392ddddcb4 --- /dev/null +++ b/test/SemaCXX/adl.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace PR40329 { + struct A { + A(int); + friend int operator->*(A, A); + }; + struct B : A { + B(); + enum E { e }; + }; + // Associated classes for B are {B, A} + // Associated classes for B::E are {B} (non-transitive in this case) + // + // If we search B::E first, we must not mark B "visited" and shortcircuit + // visiting it later, or we won't find the associated class A. + int k0 = B::e ->* B::e; // expected-error {{non-pointer-to-member type}} + int k1 = B::e ->* B(); + int k2 = B() ->* B::e; +} diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp index f89d19959b..42770030d2 100644 --- a/test/SemaCXX/anonymous-struct.cpp +++ b/test/SemaCXX/anonymous-struct.cpp @@ -9,7 +9,7 @@ struct S { #endif }; -struct { // expected-error {{anonymous structs and classes must be class members}} +struct { // expected-error {{anonymous structs and classes must be class members}} expected-warning {{does not declare anything}} }; struct E { @@ -19,7 +19,7 @@ struct E { // expected-error@-2 {{anonymous struct member 'x' has a non-trivial default constructor}} #endif }; - static struct { + static struct { // expected-warning {{does not declare anything}} }; class { int anon_priv_field; // expected-error {{anonymous struct cannot contain a private data member}} diff --git a/test/SemaCXX/anonymous-union-export.cpp b/test/SemaCXX/anonymous-union-export.cpp index 1d83d809f5..689c6b9f17 100644 --- a/test/SemaCXX/anonymous-union-export.cpp +++ b/test/SemaCXX/anonymous-union-export.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -std=c++17 -fmodules-ts -emit-obj -verify -o %t.pcm %s export module M; -export { - union { bool a; }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} +export { // expected-note 2{{export block begins here}} + union { bool a; }; // expected-error {{anonymous unions at namespace or global scope must be declared 'static'}} expected-error {{declaration of 'a' with internal linkage cannot be exported}} + static union { bool a; }; // expected-error {{declaration of 'a' with internal linkage cannot be exported}} } diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 5538ea4703..9a88439994 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -81,7 +81,7 @@ union { // expected-error{{anonymous unions at namespace or global scope must be }; extern "C++" { -union { }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} +union { int extern_cxx; }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} } static union { diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp index 6ebff8c992..495ccaf71b 100644 --- a/test/SemaCXX/array-bounds.cpp +++ b/test/SemaCXX/array-bounds.cpp @@ -296,3 +296,16 @@ namespace PR39746 { // We can still diagnose this. C &h() { return reinterpret_cast<C *>(xxx)[-1]; } // expected-warning {{array index -1 is before the beginning of the array}} } + +namespace PR41087 { + template <typename Ty> void foo() { + Ty buffer[2]; // expected-note 3{{array 'buffer' declared here}} + ((char *)buffer)[2] = 'A'; // expected-warning 1{{array index 2 is past the end of the array (which contains 2 elements)}} + ((char *)buffer)[-1] = 'A'; // expected-warning 2{{array index -1 is before the beginning of the array}} + } + + void f() { + foo<char>(); // expected-note 1{{in instantiation of function template specialization}} + foo<int>(); // expected-note 1{{in instantiation of function template specialization}} + }; +} diff --git a/test/SemaCXX/attr-callback-broken.cpp b/test/SemaCXX/attr-callback-broken.cpp new file mode 100644 index 0000000000..a5469b22ba --- /dev/null +++ b/test/SemaCXX/attr-callback-broken.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +class C_in_class { +#define HAS_THIS +#include "../Sema/attr-callback-broken.c" +#undef HAS_THIS +}; diff --git a/test/SemaCXX/attr-callback.cpp b/test/SemaCXX/attr-callback.cpp new file mode 100644 index 0000000000..ee02f7d3d2 --- /dev/null +++ b/test/SemaCXX/attr-callback.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +// expected-no-diagnostics + +class C_in_class { +#include "../Sema/attr-callback.c" +}; + +struct Base { + + void no_args_1(void (*callback)(void)); + __attribute__((callback(1))) void no_args_2(void (*callback)(void)); + __attribute__((callback(callback))) void no_args_3(void (*callback)(void)) {} + + __attribute__((callback(1, 0))) virtual void + this_tr(void (*callback)(Base *)); + + __attribute__((callback(1, this, __, this))) virtual void + this_unknown_this(void (*callback)(Base *, Base *, Base *)); + + __attribute__((callback(1))) virtual void + virtual_1(void (*callback)(void)); + + __attribute__((callback(callback))) virtual void + virtual_2(void (*callback)(void)); + + __attribute__((callback(1))) virtual void + virtual_3(void (*callback)(void)); +}; + +__attribute__((callback(1))) void +Base::no_args_1(void (*callback)(void)) { +} + +void Base::no_args_2(void (*callback)(void)) { +} + +struct Derived_1 : public Base { + + __attribute__((callback(1, 0))) virtual void + this_tr(void (*callback)(Base *)) override; + + __attribute__((callback(1))) virtual void + virtual_1(void (*callback)(void)) override {} + + virtual void + virtual_3(void (*callback)(void)) override {} +}; + +struct Derived_2 : public Base { + + __attribute__((callback(callback))) virtual void + virtual_1(void (*callback)(void)) override; + + virtual void + virtual_2(void (*callback)(void)) override; + + virtual void + virtual_3(void (*callback)(void)) override; +}; + +void Derived_2::virtual_1(void (*callback)(void)) {} + +__attribute__((callback(1))) void +Derived_2::virtual_2(void (*callback)(void)) {} + +void Derived_2::virtual_3(void (*callback)(void)) {} diff --git a/test/SemaCXX/attr-no-speculative-load-hardening.cpp b/test/SemaCXX/attr-no-speculative-load-hardening.cpp new file mode 100644 index 0000000000..eebc5278f2 --- /dev/null +++ b/test/SemaCXX/attr-no-speculative-load-hardening.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int i __attribute__((no_speculative_load_hardening)); // expected-error {{'no_speculative_load_hardening' attribute only applies to functions}} + +void f1() __attribute__((no_speculative_load_hardening)); +void f2() __attribute__((no_speculative_load_hardening(1))); // expected-error {{'no_speculative_load_hardening' attribute takes no arguments}} + +template <typename T> +void tf1() __attribute__((no_speculative_load_hardening)); + +int f3(int __attribute__((no_speculative_load_hardening)), int); // expected-error {{'no_speculative_load_hardening' attribute only applies to functions}} + +struct A { + int f __attribute__((no_speculative_load_hardening)); // expected-error {{'no_speculative_load_hardening' attribute only applies to functions}} + void mf1() __attribute__((no_speculative_load_hardening)); + static void mf2() __attribute__((no_speculative_load_hardening)); +}; + +int ci [[clang::no_speculative_load_hardening]]; // expected-error {{'no_speculative_load_hardening' attribute only applies to functions}} + +[[clang::no_speculative_load_hardening]] void cf1(); +[[clang::no_speculative_load_hardening(1)]] void cf2(); // expected-error {{'no_speculative_load_hardening' attribute takes no arguments}} + +template <typename T> +[[clang::no_speculative_load_hardening]] +void ctf1(); + +int cf3(int c[[clang::no_speculative_load_hardening]], int); // expected-error {{'no_speculative_load_hardening' attribute only applies to functions}} + +struct CA { + int f [[clang::no_speculative_load_hardening]]; // expected-error {{'no_speculative_load_hardening' attribute only applies to functions}} + [[clang::no_speculative_load_hardening]] void mf1(); + [[clang::no_speculative_load_hardening]] static void mf2(); +}; diff --git a/test/SemaCXX/attr-speculative-load-hardening.cpp b/test/SemaCXX/attr-speculative-load-hardening.cpp index bba3b6921e..ff31e4be17 100644 --- a/test/SemaCXX/attr-speculative-load-hardening.cpp +++ b/test/SemaCXX/attr-speculative-load-hardening.cpp @@ -16,6 +16,17 @@ struct A { static void mf2() __attribute__((speculative_load_hardening)); }; +void f4() __attribute__((no_speculative_load_hardening, speculative_load_hardening)); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +void f5() __attribute__((speculative_load_hardening, no_speculative_load_hardening)); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +void f6() __attribute__((no_speculative_load_hardening)); + +void f6() __attribute__((speculative_load_hardening)); // expected-error@-2 {{'no_speculative_load_hardening' and 'speculative_load_hardening' attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + int ci [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}} [[clang::speculative_load_hardening]] void cf1(); @@ -32,3 +43,16 @@ struct CA { [[clang::speculative_load_hardening]] void mf1(); [[clang::speculative_load_hardening]] static void mf2(); }; + +[[clang::speculative_load_hardening, clang::no_speculative_load_hardening]] void cf4(); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +[[clang::no_speculative_load_hardening, clang::speculative_load_hardening]] void cf5(); // expected-error {{attributes are not compatible}} +// expected-note@-1 {{conflicting attribute is here}} + +[[clang::speculative_load_hardening]] +void cf6(); + +[[clang::no_speculative_load_hardening]] +void cf6(); // expected-error@-4 {{'speculative_load_hardening' and 'no_speculative_load_hardening' attributes are not compatible}} \ +// expected-note@-1 {{conflicting attribute is here}} diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp index bafae2ab43..c5c3cff6bc 100644 --- a/test/SemaCXX/attr-unavailable.cpp +++ b/test/SemaCXX/attr-unavailable.cpp @@ -1,17 +1,16 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int &foo(int); // expected-note {{candidate}} -double &foo(double); // expected-note {{candidate}} -void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ -// expected-note{{'foo' has been explicitly marked unavailable here}} +int &foo(int); +double &foo(double); +void foo(...) __attribute__((__unavailable__)); // \ +// expected-note 2 {{'foo' has been explicitly marked unavailable here}} -void bar(...) __attribute__((__unavailable__)); // expected-note 2{{explicitly marked unavailable}} \ - // expected-note 2{{candidate function has been explicitly made unavailable}} +void bar(...) __attribute__((__unavailable__)); // expected-note 4 {{explicitly marked unavailable}} void test_foo(short* sp) { int &ir = foo(1); double &dr = foo(1.0); - foo(sp); // expected-error{{call to unavailable function 'foo'}} + foo(sp); // expected-error{{'foo' is unavailable}} void (*fp)(...) = &bar; // expected-error{{'bar' is unavailable}} void (*fp2)(...) = bar; // expected-error{{'bar' is unavailable}} @@ -24,9 +23,9 @@ namespace radar9046492 { // rdar://9046492 #define FOO __attribute__((unavailable("not available - replaced"))) -void foo() FOO; // expected-note {{candidate function has been explicitly made unavailable}} +void foo() FOO; // expected-note{{'foo' has been explicitly marked unavailable here}} void bar() { - foo(); // expected-error {{call to unavailable function 'foo': not available - replaced}} + foo(); // expected-error {{'foo' is unavailable: not available - replaced}} } } @@ -79,19 +78,19 @@ void untemplated_marked(UnavailableClass &UC) __attribute__((unavailable)) { } template <class T> void templated_calls_bar() { bar(); } // \ - // expected-error{{call to unavailable function 'bar'}} + // expected-error{{'bar' is unavailable}} template <class T> void templated_calls_bar_arg(T v) { bar(v); } // \ - // expected-error{{call to unavailable function 'bar'}} + // expected-error{{'bar' is unavailable}} template <class T> void templated_calls_bar_arg_never_called(T v) { bar(v); } template <class T> -void unavail_templated_calls_bar() __attribute__((unavailable)) { // \ - expected-note{{candidate function [with T = int] has been explicitly made unavailable}} +void unavail_templated_calls_bar() __attribute__((unavailable)) { // \ +// expected-note {{'unavail_templated_calls_bar<int>' has been explicitly marked unavailable here}} bar(5); } template <class T> -void unavail_templated_calls_bar_arg(T v) __attribute__((unavailable)) { // \ - expected-note{{candidate function [with T = int] has been explicitly made unavailable}} +void unavail_templated_calls_bar_arg(T v) __attribute__((unavailable)) { +// expected-note@-1 {{'unavail_templated_calls_bar_arg<int>' has been explicitly marked unavailable here}} bar(v); } @@ -102,34 +101,34 @@ void calls_templates_which_call_bar() { expected-note{{in instantiation of function template specialization 'templated_calls_bar_arg<int>' requested here}} unavail_templated_calls_bar<int>(); // \ - expected-error{{call to unavailable function 'unavail_templated_calls_bar'}} + expected-error{{'unavail_templated_calls_bar<int>' is unavailable}} unavail_templated_calls_bar_arg(5); // \ - expected-error{{call to unavailable function 'unavail_templated_calls_bar_arg'}} + expected-error{{'unavail_templated_calls_bar_arg<int>' is unavailable}} } -template <class T> void unavail_templated(T) __attribute__((unavailable)); // \ - expected-note{{candidate function [with T = int] has been explicitly made unavailable}} +template <class T> void unavail_templated(T) __attribute__((unavailable)); +// expected-note@-1 {{'unavail_templated<int>' has been explicitly marked unavailable here}} void calls_unavail_templated() { - unavail_templated(5); // expected-error{{call to unavailable function 'unavail_templated'}} + unavail_templated(5); // expected-error{{'unavail_templated<int>' is unavailable}} } void unavail_calls_unavail_templated() __attribute__((unavailable)) { unavail_templated(5); } -void unavailable() __attribute((unavailable)); // \ - expected-note 4{{candidate function has been explicitly made unavailable}} +void unavailable() __attribute((unavailable)); +// expected-note@-1 4 {{'unavailable' has been explicitly marked unavailable here}} struct AvailableStruct { void calls_unavailable() { unavailable(); } // \ - expected-error{{call to unavailable function 'unavailable'}} + expected-error{{'unavailable' is unavailable}} template <class U> void calls_unavailable() { unavailable(); } // \ - expected-error{{call to unavailable function 'unavailable'}} + expected-error{{'unavailable' is unavailable}} }; template <class T> struct AvailableStructTemplated { void calls_unavailable() { unavailable(); } // \ - expected-error{{call to unavailable function 'unavailable'}} + expected-error{{'unavailable' is unavailable}} template <class U> void calls_unavailable() { unavailable(); } // \ - expected-error{{call to unavailable function 'unavailable'}} + expected-error{{'unavailable' is unavailable}} }; struct __attribute__((unavailable)) UnavailableStruct { void calls_unavailable() { unavailable(); } @@ -139,3 +138,37 @@ template <class T> struct __attribute__((unavailable)) UnavailableStructTemplate void calls_unavailable() { unavailable(); } template <class U> void calls_unavailable() { unavailable(); } }; + +int unavailable_int() __attribute__((unavailable)); // expected-note 2 {{'unavailable_int' has been explicitly marked unavailable here}} +int has_default_arg(int x = unavailable_int()) { // expected-error{{'unavailable_int' is unavailable}} + return x; +} + +int has_default_arg2(int x = unavailable_int()) __attribute__((unavailable)) { + return x; +} + +template <class T> +T unavailable_template() __attribute__((unavailable)); +// expected-note@-1 {{'unavailable_template<int>' has been explicitly marked unavailable here}} + +template <class T> +int has_default_arg_template(T x = unavailable_template<T>()) {} +// expected-error@-1 {{'unavailable_template<int>' is unavailable}} + +int instantiate_it = has_default_arg_template<int>(); +// expected-note@-1 {{in instantiation of default function argument expression for 'has_default_arg_template<int>' required here}} + +template <class T> +int has_default_arg_template2(T x = unavailable_template<T>()) + __attribute__((unavailable)) {} + +__attribute__((unavailable)) +int instantiate_it2 = has_default_arg_template2<int>(); + +template <class T> +int phase_one_unavailable(int x = unavailable_int()) {} +// expected-error@-1 {{'unavailable_int' is unavailable}} + +template <class T> +int phase_one_unavailable2(int x = unavailable_int()) __attribute__((unavailable)) {} diff --git a/test/SemaCXX/auto-cxx0x.cpp b/test/SemaCXX/auto-cxx0x.cpp index 074a01bb83..b4da3f9330 100644 --- a/test/SemaCXX/auto-cxx0x.cpp +++ b/test/SemaCXX/auto-cxx0x.cpp @@ -15,3 +15,11 @@ void g() { // expected-error@-2 {{'auto' not allowed in lambda parameter}} #endif } + +void rdar47689465() { + int x = 0; + [](auto __attribute__((noderef)) *){}(&x); +#if __cplusplus == 201103L + // expected-error@-2 {{'auto' not allowed in lambda parameter}} +#endif +} diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp index 0521802172..aacf63cfab 100644 --- a/test/SemaCXX/blocks.cpp +++ b/test/SemaCXX/blocks.cpp @@ -145,3 +145,11 @@ namespace test6c { A::foo(); }); } } + +namespace test7 { +struct S {}; +void f() { + constexpr S s; + auto some_block = ^{ (void)s; }; +} +} diff --git a/test/SemaCXX/borland-extensions.cpp b/test/SemaCXX/borland-extensions.cpp index d214473031..31ebf03712 100644 --- a/test/SemaCXX/borland-extensions.cpp +++ b/test/SemaCXX/borland-extensions.cpp @@ -7,21 +7,21 @@ int dummy_function() { return 0; } // 2. test __pascal -// expected-warning@+1 {{calling convention '_pascal' ignored for this target}} +// expected-warning@+1 {{'_pascal' calling convention ignored for this target}} int _pascal f2(); -// expected-warning@+1 {{calling convention '__pascal' ignored for this target}} +// expected-warning@+1 {{'__pascal' calling convention ignored for this target}} float __pascal gi2(int, int); -// expected-warning@+1 {{calling convention '__pascal' ignored for this target}} +// expected-warning@+1 {{'__pascal' calling convention ignored for this target}} template<typename T> T g2(T (__pascal * const )(int, int)) { return 0; } struct M { - // expected-warning@+1 {{calling convention '__pascal' ignored for this target}} + // expected-warning@+1 {{'__pascal' calling convention ignored for this target}} int __pascal addP(); - // expected-warning@+1 {{calling convention '__pascal' ignored for this target}} + // expected-warning@+1 {{'__pascal' calling convention ignored for this target}} float __pascal subtractP(); }; -// expected-warning@+1 {{calling convention '__pascal' ignored for this target}} +// expected-warning@+1 {{'__pascal' calling convention ignored for this target}} template<typename T> int h2(T (__pascal M::* const )()) { return 0; } void m2() { int i; float f; @@ -34,9 +34,9 @@ void m2() { // 3. test other calling conventions int _cdecl fa3(); -// expected-warning@+1 {{calling convention '_fastcall' ignored for this target}} +// expected-warning@+1 {{'_fastcall' calling convention ignored for this target}} int _fastcall fc3(); -// expected-warning@+1 {{calling convention '_stdcall' ignored for this target}} +// expected-warning@+1 {{'_stdcall' calling convention ignored for this target}} int _stdcall fd3(); // 4. test __uuidof() diff --git a/test/SemaCXX/builtin-constant-p.cpp b/test/SemaCXX/builtin-constant-p.cpp new file mode 100644 index 0000000000..21cbaf7c69 --- /dev/null +++ b/test/SemaCXX/builtin-constant-p.cpp @@ -0,0 +1,132 @@ +// RUN: %clang_cc1 -std=c++17 -verify %s + +using intptr_t = __INTPTR_TYPE__; + +// Test interaction of constexpr and __builtin_constant_p. + +template<typename T> constexpr bool bcp(T t) { + return __builtin_constant_p(t); +} +template<typename T> constexpr bool bcp_fold(T t) { + return __builtin_constant_p(((void)(intptr_t)&t, t)); +} + +constexpr intptr_t ensure_fold_is_generally_not_enabled = // expected-error {{constant expression}} + (intptr_t)&ensure_fold_is_generally_not_enabled; // expected-note {{cast}} + +constexpr intptr_t ptr_to_int(const void *p) { + return __builtin_constant_p(1) ? (intptr_t)p : (intptr_t)p; +} + +constexpr int *int_to_ptr(intptr_t n) { + return __builtin_constant_p(1) ? (int*)n : (int*)n; +} + +int x; + +// Integer and floating point constants encountered during constant expression +// evaluation are considered constant. So is nullptr_t. +static_assert(bcp(1)); +static_assert(bcp_fold(1)); +static_assert(bcp(1.0)); +static_assert(bcp_fold(1.0)); +static_assert(bcp(nullptr)); +static_assert(bcp_fold(nullptr)); + +// Pointers to the start of strings are considered constant. +static_assert(bcp("foo")); +static_assert(bcp_fold("foo")); + +// Null pointers are considered constant. +static_assert(bcp<int*>(nullptr)); +static_assert(bcp_fold<int*>(nullptr)); +static_assert(bcp<const char*>(nullptr)); +static_assert(bcp_fold<const char*>(nullptr)); + +// Other pointers are not. +static_assert(!bcp(&x)); +static_assert(!bcp_fold(&x)); + +// Pointers cast to integers follow the rules for pointers. +static_assert(bcp(ptr_to_int("foo"))); +static_assert(bcp_fold(ptr_to_int("foo"))); +static_assert(!bcp(ptr_to_int(&x))); +static_assert(!bcp_fold(ptr_to_int(&x))); + +// Integers cast to pointers follow the integer rules. +static_assert(bcp(int_to_ptr(0))); +static_assert(bcp_fold(int_to_ptr(0))); +static_assert(bcp(int_to_ptr(123))); // GCC rejects these due to not recognizing +static_assert(bcp_fold(int_to_ptr(123))); // the bcp conditional in 'int_to_ptr' ... +static_assert(__builtin_constant_p((int*)123)); // ... but GCC accepts this + +// State mutations in the operand are not permitted. +// +// The rule GCC uses for this is not entirely understood, but seems to depend +// in some way on what local state is mentioned in the operand of +// __builtin_constant_p and where. +// +// We approximate GCC's rule by evaluating the operand in a speculative +// evaluation context; only state created within the evaluation can be +// modified. +constexpr int mutate1() { + int n = 1; + int m = __builtin_constant_p(++n); + return n * 10 + m; +} +static_assert(mutate1() == 10); + +// FIXME: GCC treats this as being non-constant because of the "n = 2", even +// though evaluation in the context of the enclosing constant expression +// succeeds without mutating any state. +constexpr int mutate2() { + int n = 1; + int m = __builtin_constant_p(n ? n + 1 : n = 2); + return n * 10 + m; +} +static_assert(mutate2() == 11); + +constexpr int internal_mutation(int unused) { + int x = 1; + ++x; + return x; +} + +constexpr int mutate3() { + int n = 1; + int m = __builtin_constant_p(internal_mutation(0)); + return n * 10 + m; +} +static_assert(mutate3() == 11); + +constexpr int mutate4() { + int n = 1; + int m = __builtin_constant_p(n ? internal_mutation(0) : 0); + return n * 10 + m; +} +static_assert(mutate4() == 11); + +// FIXME: GCC treats this as being non-constant because of something to do with +// the 'n' in the argument to internal_mutation. +constexpr int mutate5() { + int n = 1; + int m = __builtin_constant_p(n ? internal_mutation(n) : 0); + return n * 10 + m; +} +static_assert(mutate5() == 11); + +constexpr int mutate_param(bool mutate, int ¶m) { + mutate = mutate; // Mutation of internal state is OK + if (mutate) + ++param; + return param; +} +constexpr int mutate6(bool mutate) { + int n = 1; + int m = __builtin_constant_p(mutate_param(mutate, n)); + return n * 10 + m; +} +// No mutation of state outside __builtin_constant_p: evaluates to true. +static_assert(mutate6(false) == 11); +// Mutation of state outside __builtin_constant_p: evaluates to false. +static_assert(mutate6(true) == 10); diff --git a/test/SemaCXX/builtin-is-constant-evaluated.cpp b/test/SemaCXX/builtin-is-constant-evaluated.cpp new file mode 100644 index 0000000000..47b54d6ac3 --- /dev/null +++ b/test/SemaCXX/builtin-is-constant-evaluated.cpp @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu + +using size_t = decltype(sizeof(int)); + +namespace std { +inline constexpr bool is_constant_evaluated() noexcept { + return __builtin_is_constant_evaluated(); +} +} // namespace std + +extern int dummy; // expected-note 1+ {{declared here}} + +static_assert(__builtin_is_constant_evaluated()); +static_assert(noexcept(__builtin_is_constant_evaluated())); + +constexpr bool b = __builtin_is_constant_evaluated(); +static_assert(b); + +const int n = __builtin_is_constant_evaluated() ? 4 : dummy; +static_assert(n == 4); +constexpr int cn = __builtin_is_constant_evaluated() ? 11 : dummy; +static_assert(cn == 11); +// expected-error@+1 {{'bn' must be initialized by a constant expression}} +constexpr int bn = __builtin_is_constant_evaluated() ? dummy : 42; // expected-note {{non-const variable 'dummy' is not allowed}} + +const int n2 = __builtin_is_constant_evaluated() ? dummy : 42; // expected-note {{declared here}} +static_assert(n2 == 42); // expected-error {{static_assert expression is not an integral constant}} +// expected-note@-1 {{initializer of 'n2' is not a constant expression}} + +template <bool V, bool Default = std::is_constant_evaluated()> +struct Templ { static_assert(V); static_assert(Default); }; +Templ<__builtin_is_constant_evaluated()> x; // type X<true> + +template <class T> +void test_if_constexpr() { + if constexpr (__builtin_is_constant_evaluated()) { + static_assert(__is_same(T, int)); + } else { + using Test = typename T::DOES_NOT_EXIST; + } +} +template void test_if_constexpr<int>(); + +void test_array_decl() { + char x[__builtin_is_constant_evaluated() + std::is_constant_evaluated()]; + static_assert(sizeof(x) == 2, ""); +} + +void test_case_stmt(int x) { + switch (x) { + case 0: // OK + case __builtin_is_constant_evaluated(): // expected-note {{previous case}} + case std::is_constant_evaluated() + __builtin_is_constant_evaluated(): // expected-note {{previous case}} + case 1: // expected-error {{duplicate case value '1'}} + case 2: // expected-error {{duplicate case value '2'}} + break; + } +} + +constexpr size_t good_array_size() { + return std::is_constant_evaluated() ? 42 : static_cast<size_t>(-1); +} + +constexpr size_t bad_array_size() { + return std::is_constant_evaluated() ? static_cast<size_t>(-1) : 13; +} + +template <class T> +constexpr T require_constexpr(T v) { + if (!std::is_constant_evaluated()) + throw "BOOM"; + return v; +} + +void test_new_expr() { + constexpr size_t TooLarge = -1; + auto *x = new int[std::is_constant_evaluated() ? 1 : TooLarge]; // expected-error {{array is too large}} + auto *x2 = new int[std::is_constant_evaluated() ? TooLarge : 1]; // OK + auto *y = new int[1][std::is_constant_evaluated() ? TooLarge : 1]{}; // expected-error {{array is too large}} + auto *y2 = new int[1][require_constexpr(42)]; +} + +void test_alignas_operand() { + alignas(std::is_constant_evaluated() ? 8 : 2) char dummy; + static_assert(__alignof(dummy) == 8); +} + +void test_static_assert_operand() { + static_assert(std::is_constant_evaluated(), ""); +} + +void test_enumerator() { + enum MyEnum { + ZERO = 0, + ONE = std::is_constant_evaluated() + }; + static_assert(ONE == 1, ""); +} + +struct TestBitfieldWidth { + unsigned Bits : std::is_constant_evaluated(); +}; + +void test_operand_of_noexcept_fn() noexcept(std::is_constant_evaluated()); +static_assert(noexcept(test_operand_of_noexcept_fn()), ""); + + +namespace test_ref_initialization { +int x; +int y; +int &r = __builtin_is_constant_evaluated() ? x : y; +static_assert(&r == &x); + +} // namespace test_ref_initialization + +#if defined(__cpp_conditional_explicit) +struct TestConditionalExplicit { + explicit(__builtin_is_constant_evaluated()) TestConditionalExplicit(int) {} +}; +TestConditionalExplicit e = 42; +#endif diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp index ee0fe01fd1..55b01e3dc3 100644 --- a/test/SemaCXX/compare.cpp +++ b/test/SemaCXX/compare.cpp @@ -2,6 +2,7 @@ // on integer sizes. // RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare -Wtautological-constant-in-range-compare -std=c++11 %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -pedantic -verify -Wsign-compare -Wtype-limits -std=c++11 %s int test0(long a, unsigned long b) { enum EnumA {A}; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 578a057104..03491f4a87 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -2146,7 +2146,7 @@ namespace InheritedCtor { struct B : A { int n; using A::A; }; // expected-note {{here}} constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}} - struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 4{{extension}} + struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}} constexpr C c(0); struct D : A { @@ -2220,3 +2220,11 @@ namespace PointerArithmeticOverflow { constexpr int *q = (&n + 1) - (unsigned __int128)-1; // expected-error {{constant expression}} expected-note {{cannot refer to element -3402}} constexpr int *r = &(&n + 1)[(unsigned __int128)-1]; // expected-error {{constant expression}} expected-note {{cannot refer to element 3402}} } + +namespace PR40430 { + struct S { + char c[10] = "asdf"; + constexpr char foo() const { return c[3]; } + }; + static_assert(S().foo() == 'f', ""); +} diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp index 3c57ac573f..ed51cca82e 100644 --- a/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/test/SemaCXX/constant-expression-cxx1y.cpp @@ -1135,3 +1135,27 @@ constexpr bool indirect_builtin_constant_p(const char *__s) { return __builtin_constant_p(*__s); } constexpr bool n = indirect_builtin_constant_p("a"); + +__attribute__((enable_if(indirect_builtin_constant_p("a") == n, "OK"))) +int test_in_enable_if() { return 0; } +int n2 = test_in_enable_if(); + +template <bool n = indirect_builtin_constant_p("a")> +int test_in_template_param() { return 0; } +int n3 = test_in_template_param(); + +void test_in_case(int n) { + switch (n) { + case indirect_builtin_constant_p("abc"): + break; + } +} +enum InEnum1 { + ONE = indirect_builtin_constant_p("abc") +}; +enum InEnum2 : int { + TWO = indirect_builtin_constant_p("abc") +}; +enum class InEnum3 { + THREE = indirect_builtin_constant_p("abc") +}; diff --git a/test/SemaCXX/constexpr-string.cpp b/test/SemaCXX/constexpr-string.cpp index c348c0ff74..f540be8f8e 100644 --- a/test/SemaCXX/constexpr-string.cpp +++ b/test/SemaCXX/constexpr-string.cpp @@ -1,7 +1,9 @@ // RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension +// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=gnu++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -DGNUMODE // RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-signed-char // RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-wchar -DNO_PREDEFINED_WCHAR_T // RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension +// RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=gnu++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -DGNUMODE // RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-signed-char // RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only -verify -pedantic -Wno-vla-extension -fno-wchar -DNO_PREDEFINED_WCHAR_T @@ -15,6 +17,10 @@ extern "C" { extern int strncmp(const char *s1, const char *s2, size_t n); extern int memcmp(const void *s1, const void *s2, size_t n); +#ifdef GNUMODE + extern int bcmp(const void *s1, const void *s2, size_t n); +#endif + extern char *strchr(const char *s, int c); extern void *memchr(const void *s, int c, size_t n); @@ -101,12 +107,28 @@ namespace StrcmpEtc { static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1); static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 5) == 0); + static_assert(__builtin_bcmp("abaa", "abba", 3) != 0); + static_assert(__builtin_bcmp("abaa", "abba", 2) == 0); + static_assert(__builtin_bcmp("a\203", "a", 2) != 0); + static_assert(__builtin_bcmp("a\203", "a\003", 2) != 0); + static_assert(__builtin_bcmp(0, 0, 0) == 0); + static_assert(__builtin_bcmp("abab\0banana", "abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 100) != 0); // FIXME: Should we reject this? + static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 7) != 0); + static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 6) != 0); + static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 5) == 0); + extern struct Incomplete incomplete; static_assert(__builtin_memcmp(&incomplete, "", 0u) == 0); static_assert(__builtin_memcmp("", &incomplete, 0u) == 0); static_assert(__builtin_memcmp(&incomplete, "", 1u) == 42); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}} static_assert(__builtin_memcmp("", &incomplete, 1u) == 42); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}} + static_assert(__builtin_bcmp(&incomplete, "", 0u) == 0); + static_assert(__builtin_bcmp("", &incomplete, 0u) == 0); + static_assert(__builtin_bcmp(&incomplete, "", 1u) == 42); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}} + static_assert(__builtin_bcmp("", &incomplete, 1u) == 42); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}} + constexpr unsigned char ku00fe00[] = {0x00, 0xfe, 0x00}; constexpr unsigned char ku00feff[] = {0x00, 0xfe, 0xff}; constexpr signed char ks00fe00[] = {0, -2, 0}; @@ -121,11 +143,24 @@ namespace StrcmpEtc { static_assert(__builtin_memcmp(ks00feff, ks00fe00, 99) == 1); static_assert(__builtin_memcmp(ks00fe00, ks00feff, 99) == -1); + static_assert(__builtin_bcmp(ku00feff, ks00fe00, 2) == 0); + static_assert(__builtin_bcmp(ku00feff, ks00fe00, 99) != 0); + static_assert(__builtin_bcmp(ku00fe00, ks00feff, 99) != 0); + static_assert(__builtin_bcmp(ks00feff, ku00fe00, 2) == 0); + static_assert(__builtin_bcmp(ks00feff, ku00fe00, 99) != 0); + static_assert(__builtin_bcmp(ks00fe00, ku00feff, 99) != 0); + static_assert(__builtin_bcmp(ks00fe00, ks00feff, 2) == 0); + static_assert(__builtin_bcmp(ks00feff, ks00fe00, 99) != 0); + static_assert(__builtin_bcmp(ks00fe00, ks00feff, 99) != 0); + struct Bool3Tuple { bool bb[3]; }; constexpr Bool3Tuple kb000100 = {{false, true, false}}; static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, kb000100.bb, 1) == 0); static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, kb000100.bb, 2) == 1); + static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, kb000100.bb, 1) == 0); + static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, kb000100.bb, 2) != 0); + constexpr long ksl[] = {0, -1}; constexpr unsigned int kui[] = {0, 0u - 1}; constexpr unsigned long long kull[] = {0, 0ull - 1}; @@ -148,9 +183,23 @@ namespace StrcmpEtc { static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 0) == 0); static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 1) == 42); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) - 1) == 0); + static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 0) == 0); + static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 1) == 0); + static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) - 1) == 0); + static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 0) == 0); + static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 1) == 42); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) - 1) == 0); + static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 0) == 0); + static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 1) == 42); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + constexpr int a = strcmp("hello", "world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strcmp' cannot be used in a constant expression}} constexpr int b = strncmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strncmp' cannot be used in a constant expression}} constexpr int c = memcmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memcmp' cannot be used in a constant expression}} + +#ifdef GNUMODE + constexpr int d = bcmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'bcmp' cannot be used in a constant expression}} +#endif } namespace MultibyteElementTests { diff --git a/test/SemaCXX/constexpr-unsigned-high-bit.cpp b/test/SemaCXX/constexpr-unsigned-high-bit.cpp new file mode 100644 index 0000000000..19d8dcab66 --- /dev/null +++ b/test/SemaCXX/constexpr-unsigned-high-bit.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only %s + +#include <limits.h> + +constexpr unsigned inc() { + unsigned i = INT_MAX; + ++i; // should not warn value is outside range + return i; +} + +constexpr unsigned dec() { + unsigned i = INT_MIN; + --i; // should not warn value is outside range + return i; +} diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index d58cedf414..99964ef6bc 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -314,13 +314,23 @@ struct CtorDtor { } }; +namespace std { class type_info; } + void unevaluated() { - decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}} - sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}} - typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}} - decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}} - sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}} - typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}} + decltype(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}} + // expected-warning@-1 {{declaration does not declare anything}} + sizeof(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}} + // expected-error@-1 {{invalid application of 'sizeof' to an incomplete type 'void'}} + typeid(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}} + // expected-warning@-1 {{expression with side effects has no effect in an unevaluated context}} + // expected-warning@-2 {{expression result unused}} + decltype(co_yield 1); // expected-error {{'co_yield' cannot be used in an unevaluated context}} + // expected-warning@-1 {{declaration does not declare anything}} + sizeof(co_yield 2); // expected-error {{'co_yield' cannot be used in an unevaluated context}} + // expected-error@-1 {{invalid application of 'sizeof' to an incomplete type 'void'}} + typeid(co_yield 3); // expected-error {{'co_yield' cannot be used in an unevaluated context}} + // expected-warning@-1 {{expression with side effects has no effect in an unevaluated context}} + // expected-warning@-2 {{expression result unused}} } // [expr.await]p2: "An await-expression shall not appear in a default argument." @@ -328,6 +338,47 @@ void unevaluated() { // not allowed. A user may not understand that this is "outside a function." void default_argument(int arg = co_await 0) {} // expected-error {{'co_await' cannot be used outside a function}} +void await_in_catch_coroutine() { + try { + } catch (...) { // FIXME: Emit a note diagnostic pointing out the try handler on this line. + []() -> void { co_await a; }(); // OK + co_await a; // expected-error {{'co_await' cannot be used in the handler of a try block}} + } +} + +void await_nested_in_catch_coroutine() { + try { + } catch (...) { // FIXME: Emit a note diagnostic pointing out the try handler on this line. + try { + co_await a; // expected-error {{'co_await' cannot be used in the handler of a try block}} + []() -> void { co_await a; }(); // OK + } catch (...) { + co_return 123; + } + } +} + +void await_in_lambda_in_catch_coroutine() { + try { + } catch (...) { + []() -> void { co_await a; }(); // OK + } +} + +void yield_in_catch_coroutine() { + try { + } catch (...) { + co_yield 1; // expected-error {{'co_yield' cannot be used in the handler of a try block}} + } +} + +void return_in_catch_coroutine() { + try { + } catch (...) { + co_return 123; // OK + } +} + constexpr auto constexpr_deduced_return_coroutine() { co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}} // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}} @@ -598,26 +649,26 @@ template coro<bad_promise_7> no_unhandled_exception_dependent(bad_promise_7); // struct bad_promise_base { private: - void return_void(); + void return_void(); // expected-note 2 {{declared private here}} }; struct bad_promise_8 : bad_promise_base { coro<bad_promise_8> get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); - void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{made unavailable}} - void unhandled_exception() const; // expected-note 2 {{candidate}} - void unhandled_exception(void *) const; // expected-note 2 {{requires 1 argument, but 0 were provided}} + void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{marked unavailable here}} + void unhandled_exception() const; + void unhandled_exception(void *) const; }; coro<bad_promise_8> calls_unhandled_exception() { - // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}} - // FIXME: also warn about private 'return_void' here. Even though building - // the call to unhandled_exception has already failed. + // expected-error@-1 {{'unhandled_exception' is unavailable}} + // expected-error@-2 {{'return_void' is a private member}} co_await a; } template <class T> coro<T> calls_unhandled_exception_dependent(T) { - // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}} + // expected-error@-1 {{'unhandled_exception' is unavailable}} + // expected-error@-2 {{'return_void' is a private member}} co_await a; } template coro<bad_promise_8> calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}} @@ -626,14 +677,13 @@ struct bad_promise_9 { coro<bad_promise_9> get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); - void await_transform(void *); // expected-note {{candidate}} - awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}} + void await_transform(void *); + awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly marked unavailable}} void return_void(); void unhandled_exception(); }; coro<bad_promise_9> calls_await_transform() { - co_await 42; // expected-error {{call to unavailable member function 'await_transform'}} - // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}} + co_await 42; // expected-error {{'await_transform' is unavailable}} } struct bad_promise_10 { diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 6346e1c235..45a65440d5 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -189,11 +189,11 @@ namespace PR15597 { ~A() noexcept(true) = default; }; template<typename T> struct B { - B() noexcept(false) = default; // expected-error {{does not match the calculated one}} - ~B() noexcept(false) = default; // expected-error {{does not match the calculated one}} + B() noexcept(false) = default; + ~B() noexcept(false) = default; }; A<int> a; - B<int> b; // expected-note {{here}} + B<int> b; } namespace PR27941 { @@ -242,3 +242,20 @@ template <typename Type> E<Type>::E(const int&) {} // expected-error {{definition of explicitly defaulted function}} } + +namespace P1286R2 { + struct X { + X(); + }; + struct A { + struct B { + B() noexcept(A::value) = default; + X x; + }; + decltype(B()) b; + static constexpr bool value = true; + }; + A::B b; + + static_assert(noexcept(A::B()), ""); +} diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index 80efd810f0..feb483546c 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -121,11 +121,11 @@ late_delete::late_delete() = default; // expected-error {{would delete it}} // See also rdar://problem/8125400. namespace empty { - static union {}; - static union { union {}; }; - static union { struct {}; }; - static union { union { union {}; }; }; - static union { union { struct {}; }; }; - static union { struct { union {}; }; }; - static union { struct { struct {}; }; }; + static union {}; // expected-warning {{does not declare anything}} + static union { union {}; }; // expected-warning {{does not declare anything}} + static union { struct {}; }; // expected-warning {{does not declare anything}} + static union { union { union {}; }; }; // expected-warning {{does not declare anything}} + static union { union { struct {}; }; }; // expected-warning {{does not declare anything}} + static union { struct { union {}; }; }; // expected-warning {{does not declare anything}} + static union { struct { struct {}; }; }; // expected-warning {{does not declare anything}} } diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index f371891e54..9a82ec4a7b 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -327,7 +327,7 @@ namespace update_rbrace_loc_crash { struct A {}; template <typename T, typename F, int... I> std::initializer_list<T> ExplodeImpl(F p1, A<int, I...>) { - // expected-error@+1 {{reference to type 'const update_rbrace_loc_crash::Incomplete' could not bind to an rvalue of type 'void'}} + // expected-error@+1 {{reference to incomplete type 'const update_rbrace_loc_crash::Incomplete' could not bind to an rvalue of type 'void'}} return {p1(I)...}; } template <typename T, int N, typename F> diff --git a/test/SemaCXX/cxx11-gnu-attrs.cpp b/test/SemaCXX/cxx11-gnu-attrs.cpp index b020d2ae29..1e8ad1e495 100644 --- a/test/SemaCXX/cxx11-gnu-attrs.cpp +++ b/test/SemaCXX/cxx11-gnu-attrs.cpp @@ -9,18 +9,18 @@ int [[gnu::unused]] attr_on_type; int *[[gnu::unused]] attr_on_ptr; // expected-warning@-1 {{attribute 'unused' ignored, because it cannot be applied to a type}} [[gnu::fastcall]] void pr17424_1(); -// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} [[gnu::fastcall]] [[gnu::stdcall]] void pr17424_2(); -// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} -// expected-warning@-2 {{calling convention 'stdcall' ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} +// expected-warning@-2 {{'stdcall' calling convention ignored for this target}} [[gnu::fastcall]] __stdcall void pr17424_3(); -// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} -// expected-warning@-2 {{calling convention '__stdcall' ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} +// expected-warning@-2 {{'__stdcall' calling convention ignored for this target}} [[gnu::fastcall]] void pr17424_4() [[gnu::stdcall]]; -// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} -// expected-warning@-2 {{calling convention 'stdcall' ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} +// expected-warning@-2 {{'stdcall' calling convention ignored for this target}} void pr17424_5 [[gnu::fastcall]](); -// expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} // Valid cases. diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 7c3b970ae8..087982327c 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -944,6 +944,15 @@ namespace PR22117 { }(0)(0); } +namespace PR41139 { + int y = [](auto outer) { + return [](auto inner) { + using T = int(decltype(outer), decltype(inner)); + return 0; + }; + }(0)(0); +} + namespace PR23716 { template<typename T> auto f(T x) { diff --git a/test/SemaCXX/cxx1y-init-captures.cpp b/test/SemaCXX/cxx1y-init-captures.cpp index 16cffb2a91..79d56e11c4 100644 --- a/test/SemaCXX/cxx1y-init-captures.cpp +++ b/test/SemaCXX/cxx1y-init-captures.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++1y %s -verify -emit-llvm-only +// RUN: %clang_cc1 -std=c++1z %s -verify -emit-llvm-only namespace variadic_expansion { int f(int &, char &) { return 0; } @@ -214,3 +215,17 @@ namespace init_capture_undeclared_identifier { auto b = [x = typo_boo]{}; // expected-error{{use of undeclared identifier 'typo_boo'; did you mean 'typo_foo'}} auto c = [x(typo_boo)]{}; // expected-error{{use of undeclared identifier 'typo_boo'; did you mean 'typo_foo'}} } + +namespace copy_evasion { + struct A { + A(); + A(const A&) = delete; + }; + auto x = [a{A()}] {}; +#if __cplusplus >= 201702L + // ok, does not copy an 'A' +#else + // expected-error@-4 {{call to deleted}} + // expected-note@-7 {{deleted}} +#endif +} diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index c310c65140..29adc8f560 100644 --- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -409,6 +409,86 @@ B b(0, {}); } +#pragma clang diagnostic push +#pragma clang diagnostic warning "-Wctad-maybe-unsupported" +namespace test_implicit_ctad_warning { + +template <class T> +struct Tag {}; + +template <class T> +struct NoExplicit { // expected-note {{add a deduction guide to suppress this warning}} + NoExplicit(T) {} + NoExplicit(T, int) {} +}; + +// expected-warning@+1 {{'NoExplicit' may not intend to support class template argument deduction}} +NoExplicit ne(42); + +template <class U> +struct HasExplicit { + HasExplicit(U) {} + HasExplicit(U, int) {} +}; +template <class U> HasExplicit(U, int) -> HasExplicit<Tag<U>>; + +HasExplicit he(42); + +// Motivating examples from (taken from Stephan Lavavej's 2018 Cppcon talk) +template <class T, class U> +struct AmateurPair { // expected-note {{add a deduction guide to suppress this warning}} + T first; + U second; + explicit AmateurPair(const T &t, const U &u) {} +}; +// expected-warning@+1 {{'AmateurPair' may not intend to support class template argument deduction}} +AmateurPair p1(42, "hello world"); // deduces to Pair<int, char[12]> + +template <class T, class U> +struct AmateurPair2 { // expected-note {{add a deduction guide to suppress this warning}} + T first; + U second; + explicit AmateurPair2(T t, U u) {} +}; +// expected-warning@+1 {{'AmateurPair2' may not intend to support class template argument deduction}} +AmateurPair2 p2(42, "hello world"); // deduces to Pair2<int, const char*> + +template <class T, class U> +struct ProPair { + T first; U second; + explicit ProPair(T const& t, U const& u) {} +}; +template<class T1, class T2> +ProPair(T1, T2) -> ProPair<T1, T2>; +ProPair p3(42, "hello world"); // deduces to ProPair<int, const char*> +static_assert(__is_same(decltype(p3), ProPair<int, const char*>)); + +// Test that user-defined explicit guides suppress the warning even if they +// aren't used as candidates. +template <class T> +struct TestExplicitCtor { + TestExplicitCtor(T) {} +}; +template <class T> +explicit TestExplicitCtor(TestExplicitCtor<T> const&) -> TestExplicitCtor<void>; +TestExplicitCtor<int> ce1{42}; +TestExplicitCtor ce2 = ce1; +static_assert(__is_same(decltype(ce2), TestExplicitCtor<int>), ""); + +struct allow_ctad_t { + allow_ctad_t() = delete; +}; + +template <class T> +struct TestSuppression { + TestSuppression(T) {} +}; +TestSuppression(allow_ctad_t)->TestSuppression<void>; +TestSuppression ta("abc"); +static_assert(__is_same(decltype(ta), TestSuppression<const char *>), ""); +} +#pragma clang diagnostic pop + #else // expected-no-diagnostics diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp index 3c9b181f1c..8b5fd6809b 100644 --- a/test/SemaCXX/cxx1z-decomposition.cpp +++ b/test/SemaCXX/cxx1z-decomposition.cpp @@ -81,4 +81,21 @@ struct PR37352 { void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}} }; +namespace instantiate_template { + +template <typename T1, typename T2> +struct pair { + T1 a; + T2 b; +}; + +const pair<int, int> &f1(); + +int f2() { + const auto &[a, b] = f1(); + return a + b; +} + +} // namespace instantiate_template + // FIXME: by-value array copies diff --git a/test/SemaCXX/cxx2a-destroying-delete.cpp b/test/SemaCXX/cxx2a-destroying-delete.cpp index 6115774e38..553b7a7080 100644 --- a/test/SemaCXX/cxx2a-destroying-delete.cpp +++ b/test/SemaCXX/cxx2a-destroying-delete.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -fexceptions -verify %s +// RUN: %clang_cc1 -std=c++2a -verify %s namespace std { using size_t = decltype(sizeof(0)); @@ -58,11 +59,13 @@ namespace delete_selection { C(); void *operator new(std::size_t); void operator delete(void*) = delete; - void operator delete(C *, std::destroying_delete_t) = delete; + void operator delete(C *, std::destroying_delete_t) = delete; // expected-note 0-1 {{deleted here}} }; - // FIXME: This should be ill-formed, but we incorrectly decide that overload - // resolution failed (because it selected a deleted function) and thus no - // 'operator delete' should be called. + // TODO: We only diagnose the use of a deleted operator delete when exceptions + // are enabled. Otherwise we don't bother doing the lookup. +#ifdef __EXCEPTIONS + // expected-error@+2 {{attempt to use a deleted function}} +#endif C *new_C() { return new C; } struct D { diff --git a/test/SemaCXX/cxx2a-template-lambdas.cpp b/test/SemaCXX/cxx2a-template-lambdas.cpp new file mode 100644 index 0000000000..6d22be44d8 --- /dev/null +++ b/test/SemaCXX/cxx2a-template-lambdas.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +template<typename, typename> +constexpr bool is_same = false; + +template<typename T> +constexpr bool is_same<T, T> = true; + +template<typename T> +struct DummyTemplate { }; + +void func() { + auto L0 = []<typename T>(T arg) { + static_assert(is_same<T, int>); // expected-error {{static_assert failed}} + }; + L0(0); + L0(0.0); // expected-note {{in instantiation}} + + auto L1 = []<int I> { + static_assert(I == 5); // expected-error {{static_assert failed}} + }; + L1.operator()<5>(); + L1.operator()<6>(); // expected-note {{in instantiation}} + + auto L2 = []<template<typename> class T, class U>(T<U> &&arg) { + static_assert(is_same<T<U>, DummyTemplate<float>>); // // expected-error {{static_assert failed}} + }; + L2(DummyTemplate<float>()); + L2(DummyTemplate<double>()); // expected-note {{in instantiation}} +} + +template<typename T> // expected-note {{declared here}} +struct ShadowMe { + void member_func() { + auto L = []<typename T> { }; // expected-error {{'T' shadows template parameter}} + } +}; + +template<typename T> +constexpr T outer() { + return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \ + expected-note {{candidate template ignored}} +} +static_assert(outer<int>() == 123); +template int *outer<int *>(); // expected-note {{in instantiation}} diff --git a/test/SemaCXX/decl-init-ref.cpp b/test/SemaCXX/decl-init-ref.cpp index 42b9286852..fb5ca8c149 100644 --- a/test/SemaCXX/decl-init-ref.cpp +++ b/test/SemaCXX/decl-init-ref.cpp @@ -36,3 +36,12 @@ namespace PR16502 { int f(); const A &c = { 10, ++c.temporary }; } + +namespace IncompleteTest { + struct String; + // expected-error@+1 {{reference to incomplete type 'const IncompleteTest::String' could not bind to an lvalue of type 'const char [1]'}} + void takeString(const String& = "") {} // expected-note {{passing argument to parameter here}} expected-note {{candidate function}} + void test() { + takeString(); // expected-error {{no matching function for call}} + } +} diff --git a/test/SemaCXX/declspec-allocator.cpp b/test/SemaCXX/declspec-allocator.cpp new file mode 100644 index 0000000000..e1af497ba1 --- /dev/null +++ b/test/SemaCXX/declspec-allocator.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fms-compatibility -triple x86_64-windows-msvc -std=c++14 -fms-extensions -fms-compatibility-version=19.00 -verify %s + +__declspec(allocator) int err_on_data; // expected-warning {{'allocator' attribute only applies to functions}} +__declspec(allocator) struct ErrOnStruct1; // expected-warning {{place it after "struct" to apply attribute}} +struct __declspec(allocator) ErrOnStruct2 {}; // expected-warning {{'allocator' attribute only applies to functions}} +__declspec(allocator) void err_on_ret_void(); // expected-warning {{not a pointer or reference type}} +__declspec(allocator) int err_on_ret_int(); // expected-warning {{not a pointer or reference type}} +__declspec(allocator) void *accept_on_ptr1(); +__declspec(allocator) void *accept_on_ptr2(size_t); +void * __declspec(allocator) accept_on_ptr3(size_t); // expected-error {{expected unqualified-id}} + +struct Foo { int x; }; +__declspec(allocator) Foo *accept_nonvoid_ptr(size_t); diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp index c09a531c19..e4a312adae 100644 --- a/test/SemaCXX/dllexport.cpp +++ b/test/SemaCXX/dllexport.cpp @@ -69,7 +69,9 @@ __declspec(dllexport) extern int GlobalRedecl4; // expected-warning{{redeclarati // 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'}} +#ifndef MS namespace { __declspec(dllexport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllexport'}} +#endif namespace ns { __declspec(dllexport) int ExternalGlobal; } __declspec(dllexport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllexport'}} @@ -124,7 +126,9 @@ template<typename T> __declspec(dllexport) extern int VarTmplRedecl3; // expecte // 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'}} +#ifndef MS namespace { template<typename T> __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}} +#endif 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'}} @@ -363,10 +367,16 @@ ImplicitlyInstantiatedExportedTemplate<IncompleteType> implicitlyInstantiatedExp // Don't instantiate class members of templates with explicit instantiation declarations, even if they are exported. struct IncompleteType2; -template <typename T> struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl { // expected-note{{attribute is here}} +#ifdef MS +// expected-note@+2{{attribute is here}} +#endif +template <typename T> struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl { int f() { return sizeof(T); } // no-error }; -extern template struct ExportedTemplateWithExplicitInstantiationDecl<IncompleteType2>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} +#ifdef MS +// expected-warning@+2{{explicit instantiation declaration should not be 'dllexport'}} +#endif +extern template struct ExportedTemplateWithExplicitInstantiationDecl<IncompleteType2>; // Instantiate class members for explicitly instantiated exported templates. struct IncompleteType3; // expected-note{{forward declaration of 'IncompleteType3'}} @@ -398,10 +408,17 @@ struct __declspec(dllexport) ExportedBaseClass2 : public ExportedBaseClassTempla // Warn about explicit instantiation declarations of dllexport classes. template <typename T> struct ExplicitInstantiationDeclTemplate {}; -extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} expected-note{{attribute is here}} +#ifdef MS +// expected-warning@+2{{explicit instantiation declaration should not be 'dllexport'}} expected-note@+2{{attribute is here}} +#endif +extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>; -template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate {}; // expected-note{{attribute is here}} -extern template struct ExplicitInstantiationDeclExportedTemplate<int>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} +template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate {}; +#ifdef MS +// expected-note@-2{{attribute is here}} +// expected-warning@+2{{explicit instantiation declaration should not be 'dllexport'}} +#endif +extern template struct ExplicitInstantiationDeclExportedTemplate<int>; namespace { struct InternalLinkageType {}; } struct __declspec(dllexport) PR23308 { @@ -434,6 +451,12 @@ template <typename T> struct ExplicitlyInstantiatedTemplate { void func() {} }; template struct ExplicitlyInstantiatedTemplate<int>; template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} }; template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>; +template <typename T> struct ExplicitlyExportDeclaredInstantiatedTemplate { void func() {} }; +extern template struct ExplicitlyExportDeclaredInstantiatedTemplate<int>; +#ifndef MS +// expected-warning@+2{{'dllexport' attribute ignored on explicit instantiation definition}} +#endif +template struct __declspec(dllexport) ExplicitlyExportDeclaredInstantiatedTemplate<int>; template <typename T> struct ExplicitlyImportInstantiatedTemplate { void func() {} }; template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate<int>; diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp index 04c33e9fb5..73aea57ba2 100644 --- a/test/SemaCXX/dllimport.cpp +++ b/test/SemaCXX/dllimport.cpp @@ -121,7 +121,9 @@ __declspec(dllimport) extern int GlobalRedecl5; // expected-warning{{redeclarati // 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'}} +#ifndef MS namespace { __declspec(dllimport) int InternalGlobal; } // expected-error{{'(anonymous namespace)::InternalGlobal' must have external linkage when declared 'dllimport'}} +#endif namespace ns { __declspec(dllimport) int ExternalGlobal; } __declspec(dllimport) auto InternalAutoTypeGlobal = Internal(); // expected-error{{'InternalAutoTypeGlobal' must have external linkage when declared 'dllimport'}} @@ -213,7 +215,9 @@ template<typename T> __declspec(dllimport) extern int VarTmplRedecl4; // expecte // 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'}} +#ifndef MS namespace { template<typename T> __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllimport'}} +#endif 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'}} diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp index ba520b047a..fd1375136a 100644 --- a/test/SemaCXX/enable_if.cpp +++ b/test/SemaCXX/enable_if.cpp @@ -514,3 +514,22 @@ namespace TypeOfFn { static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, ""); } + +namespace InConstantContext { +void foo(const char *s) __attribute__((enable_if(((void)__builtin_constant_p(*s), true), "trap"))) {} + +void test() { + InConstantContext::foo("abc"); +} +} // namespace InConstantContext + +namespace StringLiteralDetector { + void need_string_literal(const char *p) __attribute__((enable_if(__builtin_constant_p(p), "argument is not a string literal"))); // expected-note 2{{not a string literal}} + void test(const char *unknown) { + need_string_literal("foo"); + need_string_literal(unknown); // expected-error {{no matching function}} + constexpr char str[] = "bar"; + need_string_literal(str); // expected-error {{no matching function}} + } +} + diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp index 9e76783ca8..1e786adaa1 100644 --- a/test/SemaCXX/exceptions.cpp +++ b/test/SemaCXX/exceptions.cpp @@ -7,6 +7,7 @@ struct A; // expected-note 4 {{forward declaration of 'A'}} struct Abstract { virtual void f() = 0; }; // expected-note {{unimplemented pure virtual method 'f'}} void trys() { + int k = 42; try { } catch(int i) { // expected-note {{previous definition}} int j = i; @@ -18,6 +19,10 @@ void trys() { } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'A'}} } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}} } catch(...) { + int ref = k; + { + int ref = k; + } int j = i; // expected-error {{use of undeclared identifier 'i'}} } diff --git a/test/SemaCXX/extended-usual-deallocation-functions.cpp b/test/SemaCXX/extended-usual-deallocation-functions.cpp new file mode 100644 index 0000000000..22a28a4b6c --- /dev/null +++ b/test/SemaCXX/extended-usual-deallocation-functions.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -fexceptions -std=c++2a -fsized-deallocation -fno-aligned-allocation -verify %s +// RUN: %clang_cc1 -fexceptions -std=c++17 -fsized-deallocation -fno-aligned-allocation -verify %s +// RUN: %clang_cc1 -fexceptions -std=c++14 -fsized-deallocation -faligned-allocation -DHAS_ALIGN -verify %s +// RUN: %clang_cc1 -fexceptions -std=c++11 -fsized-deallocation -faligned-allocation -DHAS_ALIGN -verify %s + +// Test that we handle aligned deallocation, sized deallocation, and destroying +// delete as usual deallocation functions even if they are used as extensions +// prior to C++17. + +namespace std { +using size_t = decltype(sizeof(0)); +enum class align_val_t : size_t; + +struct destroying_delete_t { + struct __construct { explicit __construct() = default; }; + explicit destroying_delete_t(__construct) {} +}; + +inline constexpr destroying_delete_t destroying_delete(destroying_delete_t::__construct()); +} + +// FIXME: Should destroying delete really be on in all dialects by default? +struct A { + void operator delete(void*) = delete; + void operator delete(A*, std::destroying_delete_t) = delete; // expected-note {{deleted}} +}; +void ATest(A* a) { delete a; } // expected-error {{deleted}} + +struct B { + void operator delete(void*) = delete; // expected-note {{deleted}} + void operator delete(void*, std::size_t) = delete; +}; +void BTest(B *b) { delete b; }// expected-error {{deleted}} + + +struct alignas(128) C { +#ifndef HAS_ALIGN + // expected-note@+2 {{deleted}} +#endif + void operator delete(void*) = delete; +#ifdef HAS_ALIGN + // expected-note@+2 {{deleted}} +#endif + void operator delete(void*, std::align_val_t) = delete; +}; +void CTest(C *c) { delete c; } // expected-error {{deleted}} + +struct D { + void operator delete(void*) = delete; + void operator delete(D*, std::destroying_delete_t) = delete; // expected-note {{deleted}} + void operator delete(D*, std::destroying_delete_t, std::size_t) = delete; + void operator delete(D*, std::destroying_delete_t, std::align_val_t) = delete; + void operator delete(D*, std::destroying_delete_t, std::size_t, std::align_val_t) = delete; +}; +void DTest(D *d) { delete d; } // expected-error {{deleted}} + +struct alignas(128) E { + void operator delete(void*) = delete; + void operator delete(E*, std::destroying_delete_t) = delete; + void operator delete(E*, std::destroying_delete_t, std::size_t) = delete; + void operator delete(E*, std::destroying_delete_t, std::align_val_t) = delete; + void operator delete(E*, std::destroying_delete_t, std::size_t, std::align_val_t) = delete; +#ifdef HAS_ALIGN + // expected-note@-3 {{deleted}} +#else + // expected-note@-7 {{deleted}} +#endif +}; +void ETest(E *e) { delete e; } // expected-error {{deleted}} diff --git a/test/SemaCXX/friend-template-redecl.cpp b/test/SemaCXX/friend-template-redecl.cpp index 3e05964fb2..4ee03c6f63 100644 --- a/test/SemaCXX/friend-template-redecl.cpp +++ b/test/SemaCXX/friend-template-redecl.cpp @@ -1,7 +1,5 @@ // RUN: %clang_cc1 -std=c++17 -verify -emit-llvm-only %s -// expected-no-diagnostics - template <class T> void bar(const T &t) { foo(t); } template <class> @@ -18,3 +16,11 @@ void f() { foo(x); bar(x); } + +template<typename T> void droid(); +struct X { + template<typename T> friend void ::droid(); + template<int N> friend void ::droid(); // expected-error {{does not match}} + // FIXME: We should produce a note for the above candidate explaining why + // it's not the droid we're looking for. +}; diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp index f91e670c0c..34d2acc754 100644 --- a/test/SemaCXX/function-redecl.cpp +++ b/test/SemaCXX/function-redecl.cpp @@ -125,3 +125,9 @@ bool Foo::isGood() { // expected-error {{out-of-line definition of 'isGood' does } void Foo::beEvil() {} // expected-error {{out-of-line definition of 'beEvil' does not match any declaration in namespace 'redecl_typo::Foo'; did you mean 'BeEvil'?}} } + +struct CVQualFun { + void func(int a, int &b); // expected-note {{type of 2nd parameter of member declaration does not match definition ('int &' vs 'int')}} +}; + +void CVQualFun::func(const int a, int b) {} // expected-error {{out-of-line definition of 'func' does not match any declaration in 'CVQualFun'}} diff --git a/test/SemaCXX/incomplete-call.cpp b/test/SemaCXX/incomplete-call.cpp index 6f5169ee8a..0fb1ef5f07 100644 --- a/test/SemaCXX/incomplete-call.cpp +++ b/test/SemaCXX/incomplete-call.cpp @@ -48,6 +48,10 @@ void test_incomplete_object_call(C& c) { c(); // expected-error{{incomplete type in call to object of type}} } +void test_incomplete_object_dtor(C *p) { + p.~C(); // expected-error{{member reference type 'C *' is a pointer; did you mean to use '->'?}} +} + namespace pr18542 { struct X { int count; diff --git a/test/SemaCXX/int-ptr-cast-SFINAE.cpp b/test/SemaCXX/int-ptr-cast-SFINAE.cpp new file mode 100644 index 0000000000..5782a6dbae --- /dev/null +++ b/test/SemaCXX/int-ptr-cast-SFINAE.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++17 + +void foo(int* a, int *b) { + a -= b; // expected-warning {{incompatible integer to pointer conversion assigning to 'int *' from}} +} + +template<typename T> T declval(); +struct true_type { static const bool value = true; }; +struct false_type { static const bool value = false; }; +template<bool, typename T, typename U> struct select { using type = T; }; +template<typename T, typename U> struct select<false, T, U> { using type = U; }; + + +template<typename T> +typename select<(sizeof(declval<T>() -= declval<T>(), 1) != 1), true_type, false_type>::type test(...); +template<typename T> false_type test(...); + +template<typename T> +static const auto has_minus_assign = decltype(test<T>())::value; + +static_assert(has_minus_assign<int*>, "failed"); // expected-error {{static_assert failed due to requirement 'has_minus_assign<int *>' "failed"}} diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 4565345fc6..1833400be3 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -586,25 +586,30 @@ namespace PR25627_dont_odr_use_local_consts { namespace ConversionOperatorDoesNotHaveDeducedReturnType { auto x = [](int){}; - auto y = [](auto) -> void {}; + auto y = [](auto &v) -> void { v.n = 0; }; using T = decltype(x); using U = decltype(y); using ExpectedTypeT = void (*)(int); template<typename T> - using ExpectedTypeU = void (*)(T); + using ExpectedTypeU = void (*)(T&); struct X { + friend auto T::operator()(int) const; friend T::operator ExpectedTypeT() const; - // Formally, this is invalid, because the return type of the conversion - // function for a generic lambda expression is an unspecified decltype - // type, which this should not match. However, this declaration is - // functionally equivalent to that one, so we're permitted to choose to - // accept this. + // FIXME: The first of these should match. The second should not. template<typename T> - friend U::operator ExpectedTypeU<T>() const; + friend void U::operator()(T&) const; // expected-error {{does not match}} + template<typename T> + friend U::operator ExpectedTypeU<T>() const; // expected-error {{does not match}} + + private: + int n; }; + // Should be OK: lambda's call operator is a friend. + void use(X &x) { y(x); } + // This used to crash in return type deduction for the conversion opreator. struct A { int n; void f() { +[](decltype(n)) {}; } }; } diff --git a/test/SemaCXX/libcxx_valarray_hack.cpp b/test/SemaCXX/libcxx_valarray_hack.cpp new file mode 100644 index 0000000000..03dc573129 --- /dev/null +++ b/test/SemaCXX/libcxx_valarray_hack.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify + +// This is a test for a hack in Clang that works around an issue with libc++'s +// <valarray> implementation. The <valarray> header contains explicit +// instantiations of functions that it declared with the internal_linkage +// attribute, which are ill-formed by [temp.explicit]p13 (and meaningless). + +#ifdef BE_THE_HEADER + +#pragma GCC system_header +namespace std { + using size_t = __SIZE_TYPE__; + template<typename T> struct valarray { + __attribute__((internal_linkage)) valarray(size_t) {} + __attribute__((internal_linkage)) ~valarray() {} + }; + + extern template valarray<size_t>::valarray(size_t); + extern template valarray<size_t>::~valarray(); +} + +#else + +#define BE_THE_HEADER +#include "libcxx_valarray_hack.cpp" + +template<typename T> struct foo { + __attribute__((internal_linkage)) void x() {}; +}; +extern template void foo<int>::x(); // expected-error {{explicit instantiation declaration of 'x' with internal linkage}} + +#endif diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 2c4659afa3..3fcee50e63 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -51,7 +51,7 @@ struct CheckExcSpec { int n = 0; }; struct CheckExcSpecFail { - CheckExcSpecFail() noexcept(true) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} + CheckExcSpecFail() noexcept(true) = default; // ok, but calls terminate() on exception ThrowCtor tc = 123; }; diff --git a/test/SemaCXX/modules-ts.cppm b/test/SemaCXX/modules-ts.cppm index c07ee82e31..1081995c58 100644 --- a/test/SemaCXX/modules-ts.cppm +++ b/test/SemaCXX/modules-ts.cppm @@ -49,8 +49,12 @@ int use_a = a; // expected-error {{declaration of 'a' must be imported from modu import foo; export {} // expected-error {{export declaration cannot be empty}} -export { ; } -export { static_assert(true); } +export { // expected-note {{begins here}} + ; // expected-warning {{ISO C++20 does not permit an empty declaration to appear in an export block}} +} +export { // expected-note {{begins here}} + static_assert(true); // expected-warning {{ISO C++20 does not permit a static_assert declaration to appear in an export block}} +} int use_b = b; int use_n = n; // FIXME: this should not be visible, because it is not exported @@ -74,7 +78,7 @@ struct S { // language rules right now, but (per personal correspondence between zygoloid // and gdr) is the intent. #if TEST == 1 -export { +export { // expected-note {{export block begins here}} extern "C++" { namespace NestedExport { export { // expected-error {{appears within another export}} diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 870a5921d2..4db1206b6c 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -65,6 +65,12 @@ void good_news() typedef foo x[2]; typedef foo y[2][2]; x* f3 = new y; + +#if __cplusplus >= 201103L + (void)new int[]{}; + (void)new int[]{1, 2, 3}; + (void)new char[]{"hello"}; +#endif } struct abstract { @@ -126,9 +132,14 @@ void bad_news(int *ip) (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}} // This must fail, because any member version hides all global versions. (void)new U; // expected-error {{no matching function for call to 'operator new'}} - (void)new (int[]); // expected-error {{array size must be specified in new expressions}} + (void)new (int[]); // expected-error {{array size must be specified in new expression with no initializer}} (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}} - // Some lacking cases due to lack of sema support. + (void)new int[]; // expected-error {{array size must be specified in new expression with no initializer}} + (void)new int[](); // expected-error {{cannot determine allocated array size from initializer}} + // FIXME: This is a terrible diagnostic. +#if __cplusplus < 201103L + (void)new int[]{}; // expected-error {{array size must be specified in new expression with no initializer}} +#endif } void good_deletes() @@ -601,3 +612,12 @@ struct A { void g() { this->::delete; } // expected-error {{expected unqualified-id}} }; } + +#if __cplusplus >= 201103L +template<typename ...T> int *dependent_array_size(T ...v) { + return new int[]{v...}; // expected-error {{cannot initialize}} +} +int *p0 = dependent_array_size(); +int *p3 = dependent_array_size(1, 2, 3); +int *fail = dependent_array_size("hello"); // expected-note {{instantiation of}} +#endif diff --git a/test/SemaCXX/overload-template.cpp b/test/SemaCXX/overload-template.cpp new file mode 100644 index 0000000000..0a23788ef3 --- /dev/null +++ b/test/SemaCXX/overload-template.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +enum copy_traits { movable = 1 }; + +template <int> +struct optional_ctor_base {}; +template <typename T> +struct ctor_copy_traits { + // this would produce a c++98-compat warning, which would erroneously get the + // no-matching-function-call error's notes attached to it (or suppress those + // notes if this diagnostic was suppressed, as it is in this case) + static constexpr int traits = copy_traits::movable; +}; +template <typename T> +struct optional : optional_ctor_base<ctor_copy_traits<T>::traits> { + template <typename U> + constexpr optional(U&& v); +}; +struct A {}; +struct XA { + XA(const A&); +}; +struct B {}; +struct XB { + XB(const B&); + XB(const optional<B>&); +}; +struct YB : XB { + using XB::XB; +}; +void InsertRow(const XA&, const YB&); // expected-note {{candidate function not viable: no known conversion from 'int' to 'const XA' for 1st argument}} +void ReproducesBugSimply() { + InsertRow(3, B{}); // expected-error {{no matching function for call to 'InsertRow'}} +} + diff --git a/test/SemaCXX/pr30559.cpp b/test/SemaCXX/pr30559.cpp new file mode 100644 index 0000000000..bcd2385fdd --- /dev/null +++ b/test/SemaCXX/pr30559.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +template < bool, class > struct A {}; +template < class, int > void f () {}; +template < class T, int > +decltype (f < T, 1 >) f (T t, typename A < t == 0, int >::type) {}; + +struct B {}; + +int main () +{ + f < B, 0 >; + return 0; +} + +template <typename T> +auto foo(T x) -> decltype((x == nullptr), *x) { + return *x; +} + +void bar() { + foo(new int); +} diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index 0b520e0af1..aa5a45eafb 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -678,7 +678,7 @@ namespace { struct a0is0 {}; struct b0is0 {}; int g() { - 0 [ // expected-error {{subscripted value is not an array}} + 0 [ sizeof(c0is0)]; // expected-error {{use of undeclared identifier}} }; } diff --git a/test/SemaCXX/unknown-type-name.cpp b/test/SemaCXX/unknown-type-name.cpp index 9086c9acc4..bacdee4b37 100644 --- a/test/SemaCXX/unknown-type-name.cpp +++ b/test/SemaCXX/unknown-type-name.cpp @@ -72,9 +72,7 @@ void f(int, T::type x, char) { } // expected-error{{missing 'typename'}} int *p; -// FIXME: We should assume that 'undeclared' is a type, not a parameter name -// here, and produce an 'unknown type name' diagnostic instead. -int f1(undeclared, int); // expected-error{{requires a type specifier}} +int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}} int f2(undeclared, 0); // expected-error{{undeclared identifier}} diff --git a/test/SemaCXX/virtual-override-x64.cpp b/test/SemaCXX/virtual-override-x64.cpp index 8d5aad8889..5b9b2148f0 100644 --- a/test/SemaCXX/virtual-override-x64.cpp +++ b/test/SemaCXX/virtual-override-x64.cpp @@ -6,7 +6,7 @@ namespace PR14339 { class A { public: - virtual void __attribute__((thiscall)) f(); // expected-warning {{calling convention 'thiscall' ignored for this target}} + virtual void __attribute__((thiscall)) f(); // expected-warning {{'thiscall' calling convention ignored for this target}} }; class B : public A { @@ -16,7 +16,7 @@ namespace PR14339 { class C : public A { public: - void __attribute__((thiscall)) f(); // expected-warning {{calling convention 'thiscall' ignored for this target}} + void __attribute__((thiscall)) f(); // expected-warning {{'thiscall' calling convention ignored for this target}} }; class D : public A { @@ -26,7 +26,7 @@ namespace PR14339 { class E { public: - virtual void __attribute__((stdcall)) g(); // expected-warning {{calling convention 'stdcall' ignored for this target}} + virtual void __attribute__((stdcall)) g(); // expected-warning {{'stdcall' calling convention ignored for this target}} }; class F : public E { diff --git a/test/SemaCXX/warn-bad-memaccess.cpp b/test/SemaCXX/warn-bad-memaccess.cpp index 55ce4a0da0..c7320901fc 100644 --- a/test/SemaCXX/warn-bad-memaccess.cpp +++ b/test/SemaCXX/warn-bad-memaccess.cpp @@ -3,7 +3,8 @@ extern "C" void *memset(void *, int, unsigned); extern "C" void *memmove(void *s1, const void *s2, unsigned n); extern "C" void *memcpy(void *s1, const void *s2, unsigned n); -extern "C" void *memcmp(void *s1, const void *s2, unsigned n); +extern "C" int memcmp(void *s1, const void *s2, unsigned n); +extern "C" int bcmp(void *s1, const void *s2, unsigned n); // Redeclare without the extern "C" to test that we still figure out that this @@ -59,6 +60,12 @@ void test_warn() { memcmp(0, &x1, sizeof x1); // \ // 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}} + bcmp(&x1, 0, sizeof x1); // \ + // expected-warning{{first operand of this 'bcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + bcmp(0, &x1, sizeof x1); // \ + // expected-warning{{second operand of this 'bcmp' 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); // \ // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ diff --git a/test/SemaCXX/warn-float-conversion.cpp b/test/SemaCXX/warn-float-conversion.cpp index 7dec4844b0..fad1ff147e 100644 --- a/test/SemaCXX/warn-float-conversion.cpp +++ b/test/SemaCXX/warn-float-conversion.cpp @@ -44,17 +44,17 @@ void Convert(float f, double d, long double ld) { void CompoundAssignment() { int x = 3; - x += 1.234; //expected-warning{{conversion}} - x -= -0.0; //expected-warning{{conversion}} - x *= 1.1f; //expected-warning{{conversion}} - x /= -2.2f; //expected-warning{{conversion}} + x += 1.234; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x -= -0.0; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x *= 1.1f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} + x /= -2.2f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} - int y = x += 1.4f; //expected-warning{{conversion}} + int y = x += 1.4f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} float z = 1.1f; double w = -2.2; - y += z + w; //expected-warning{{conversion}} + y += z + w; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} } # 1 "foo.h" 3 diff --git a/test/SemaCXX/warn-infinite-recursion.cpp b/test/SemaCXX/warn-infinite-recursion.cpp index bbeff92a65..e5a5a18b65 100644 --- a/test/SemaCXX/warn-infinite-recursion.cpp +++ b/test/SemaCXX/warn-infinite-recursion.cpp @@ -53,19 +53,28 @@ int j() { // expected-warning{{call itself}} return 5 + j(); } -void k() { // expected-warning{{call itself}} +// Don't warn on infinite loops +void k() { while(true) { k(); } } -// Don't warn on infinite loops void l() { while (true) {} l(); } +void m() { + static int count = 5; + if (count >0) { + count--; + l(); + } + while (true) {} +} + class S { static void a(); void b(); diff --git a/test/SemaCXX/warn-static-outside-class-definition.cpp b/test/SemaCXX/warn-static-outside-class-definition.cpp new file mode 100644 index 0000000000..5235d35cb1 --- /dev/null +++ b/test/SemaCXX/warn-static-outside-class-definition.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s + +struct C { + template <typename T> static int foo(T); +}; + +template <typename T> static int C::foo(T) { + //expected-warning@-1 {{'static' can only be specified inside the class definition}} + return 0; +} + diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index f959beb622..ac89ea86f0 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -239,7 +239,7 @@ void sls_fun_bad_1() { } void sls_fun_bad_2() { - sls_mu.Lock(); + sls_mu.Lock(); // expected-note{{mutex acquired here}} sls_mu.Lock(); // \ // expected-warning{{acquiring mutex 'sls_mu' that is already held}} sls_mu.Unlock(); @@ -365,7 +365,7 @@ void aa_fun_bad_1() { } void aa_fun_bad_2() { - glock.globalLock(); + glock.globalLock(); // expected-note{{mutex acquired here}} glock.globalLock(); // \ // expected-warning{{acquiring mutex 'aa_mu' that is already held}} glock.globalUnlock(); @@ -726,26 +726,26 @@ void shared_bad_2() { } void shared_bad_3() { - sls_mu.Lock(); + sls_mu.Lock(); // expected-note {{mutex acquired here}} sls_mu.ReaderUnlock(); // \ // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}} } void shared_bad_4() { - sls_mu.ReaderLock(); + sls_mu.ReaderLock(); // expected-note {{mutex acquired here}} sls_mu.ExclusiveUnlock(); // \ // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}} } void shared_bad_5() { - sls_mu.Lock(); + sls_mu.Lock(); // expected-note {{mutex acquired here}} sls_mu.PromoteShared(); // \ // expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}} sls_mu.ExclusiveUnlock(); } void shared_bad_6() { - sls_mu.ReaderLock(); + sls_mu.ReaderLock(); // expected-note {{mutex acquired here}} sls_mu.DemoteExclusive(); // \ // expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}} sls_mu.ReaderUnlock(); @@ -1691,7 +1691,7 @@ struct TestScopedLockable { } void foo3() { - MutexLock mulock_a(&mu1); + MutexLock mulock_a(&mu1); // expected-note{{mutex acquired here}} MutexLock mulock_b(&mu1); // \ // expected-warning {{acquiring mutex 'mu1' that is already held}} } @@ -2710,14 +2710,14 @@ void doubleUnlock() { } void doubleLock1() { - RelockableExclusiveMutexLock scope(&mu); + RelockableExclusiveMutexLock scope(&mu); // expected-note{{mutex acquired here}} scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} } void doubleLock2() { RelockableExclusiveMutexLock scope(&mu); scope.Unlock(); - scope.Lock(); + scope.Lock(); // expected-note{{mutex acquired here}} scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} } @@ -2754,7 +2754,7 @@ public: }; void relockShared2() { - MemberLock lock; + MemberLock lock; // expected-note{{mutex acquired here}} lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}} } @@ -2861,7 +2861,7 @@ void join() EXCLUSIVE_LOCKS_REQUIRED(mu) { void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) { MutexUnlock scope(&mu); - scope.Lock(); + scope.Lock(); // expected-note{{mutex acquired here}} scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} } @@ -3164,7 +3164,7 @@ void Foo::test7() { void Foo::test8() { - mu_->Lock(); + mu_->Lock(); // expected-note 2 {{mutex acquired here}} 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(); @@ -3298,7 +3298,7 @@ void test0() { foo.lock(); foo.unlock(); - foo.lock(); + foo.lock(); // expected-note{{mutex acquired here}} foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}} foo.unlock(); foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}} @@ -3311,7 +3311,7 @@ void test1() { foo.a = 0; foo.unlock1(); - foo.lock1(); + foo.lock1(); // expected-note{{mutex acquired here}} foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} foo.a = 0; foo.unlock1(); @@ -3325,7 +3325,7 @@ int test2() { int d1 = foo.a; foo.unlock1(); - foo.slock1(); + foo.slock1(); // expected-note{{mutex acquired here}} foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} int d2 = foo.a; foo.unlock1(); @@ -3342,7 +3342,7 @@ void test3() { foo.c = 0; foo.unlock3(); - foo.lock3(); + foo.lock3(); // expected-note 3 {{mutex acquired here}} foo.lock3(); // \ // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \ // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \ @@ -3366,7 +3366,7 @@ void testlots() { foo.c = 0; foo.unlocklots(); - foo.locklots(); + foo.locklots(); // expected-note 3 {{mutex acquired here}} foo.locklots(); // \ // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \ // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \ @@ -3524,7 +3524,7 @@ void test() { LockAllGraphs(); g2.mu_.Unlock(); - LockAllGraphs(); + LockAllGraphs(); // expected-note{{mutex acquired here}} g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}} g1.mu_.Unlock(); } diff --git a/test/SemaCXX/warn-unsequenced-cxx17.cpp b/test/SemaCXX/warn-unsequenced-cxx17.cpp deleted file mode 100644 index 3c221fb8d6..0000000000 --- a/test/SemaCXX/warn-unsequenced-cxx17.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wno-unused %s - -void test() { - int xs[10]; - int *p = xs; - // expected-no-diagnostics - p[(long long unsigned)(p = 0)]; // ok -} diff --git a/test/SemaCXX/warn-unsequenced.cpp b/test/SemaCXX/warn-unsequenced.cpp index 6d4468cabf..bb8fd8be3d 100644 --- a/test/SemaCXX/warn-unsequenced.cpp +++ b/test/SemaCXX/warn-unsequenced.cpp @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-unused %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx11 -std=c++11 -Wno-unused -Wno-uninitialized \ +// RUN: -Wunsequenced -Wno-c++17-extensions -Wno-c++14-extensions %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx17 -std=c++17 -Wno-unused -Wno-uninitialized \ +// RUN: -Wunsequenced -Wno-c++17-extensions -Wno-c++14-extensions %s int f(int, int = 0); @@ -10,81 +13,107 @@ struct S { int n; }; +// TODO: Implement the C++17 sequencing rules. void test() { int a; int xs[10]; ++a = 0; // ok - a + ++a; // expected-warning {{unsequenced modification and access to 'a'}} + a + ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} a = ++a; // ok - a + a++; // expected-warning {{unsequenced modification and access to 'a'}} - a = a++; // expected-warning {{multiple unsequenced modifications to 'a'}} + a + a++; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + a = a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} ++ ++a; // ok (a++, a++); // ok - ++a + ++a; // expected-warning {{multiple unsequenced modifications to 'a'}} - a++ + a++; // expected-warning {{multiple unsequenced modifications}} + ++a + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + a++ + a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} (a++, a) = 0; // ok, increment is sequenced before value computation of LHS a = xs[++a]; // ok - a = xs[a++]; // expected-warning {{multiple unsequenced modifications}} - (a ? xs[0] : xs[1]) = ++a; // expected-warning {{unsequenced modification and access}} + a = xs[a++]; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + (a ? xs[0] : xs[1]) = ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}} a = (++a, ++a); // ok a = (a++, ++a); // ok - a = (a++, a++); // expected-warning {{multiple unsequenced modifications}} + a = (a++, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} f(a, a); // ok - f(a = 0, a); // expected-warning {{unsequenced modification and access}} - f(a, a += 0); // expected-warning {{unsequenced modification and access}} - f(a = 0, a = 0); // expected-warning {{multiple unsequenced modifications}} + f(a = 0, a); // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + f(a, a += 0); // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + f(a = 0, a = 0); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} a = f(++a); // ok a = f(a++); // ok - a = f(++a, a++); // expected-warning {{multiple unsequenced modifications}} + a = f(++a, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} // Compound assignment "A OP= B" is equivalent to "A = A OP B" except that A // is evaluated only once. (++a, a) = 1; // ok (++a, a) += 1; // ok a = ++a; // ok - a += ++a; // expected-warning {{unsequenced modification and access}} + a += ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}} A agg1 = { a++, a++ }; // ok - A agg2 = { a++ + a, a++ }; // expected-warning {{unsequenced modification and access}} + A agg2 = { a++ + a, a++ }; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} - S str1(a++, a++); // expected-warning {{multiple unsequenced modifications}} + S str1(a++, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} S str2 = { a++, a++ }; // ok - S str3 = { a++ + a, a++ }; // expected-warning {{unsequenced modification and access}} + S str3 = { a++ + a, a++ }; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} struct Z { A a; S s; } z = { { ++a, ++a }, { ++a, ++a } }; // ok a = S { ++a, a++ }.n; // ok A { ++a, a++ }.x; // ok - a = A { ++a, a++ }.x; // expected-warning {{unsequenced modifications}} - A { ++a, a++ }.x + A { ++a, a++ }.y; // expected-warning {{unsequenced modifications}} + a = A { ++a, a++ }.x; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + A { ++a, a++ }.x + A { ++a, a++ }.y; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} (xs[2] && (a = 0)) + a; // ok (0 && (a = 0)) + a; // ok - (1 && (a = 0)) + a; // expected-warning {{unsequenced modification and access}} + (1 && (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (xs[3] || (a = 0)) + a; // ok - (0 || (a = 0)) + a; // expected-warning {{unsequenced modification and access}} + (0 || (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (1 || (a = 0)) + a; // ok (xs[4] ? a : ++a) + a; // ok - (0 ? a : ++a) + a; // expected-warning {{unsequenced modification and access}} + (0 ? a : ++a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (1 ? a : ++a) + a; // ok - (0 ? a : a++) + a; // expected-warning {{unsequenced modification and access}} + (0 ? a : a++) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (1 ? a : a++) + a; // ok (xs[5] ? ++a : ++a) + a; // FIXME: warn here - (++a, xs[6] ? ++a : 0) + a; // expected-warning {{unsequenced modification and access}} + (++a, xs[6] ? ++a : 0) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} // Here, the read of the fourth 'a' might happen before or after the write to // the second 'a'. - a += (a++, a) + a; // expected-warning {{unsequenced modification and access}} + a += (a++, a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} int *p = xs; a = *(a++, p); // ok a = a++ && a; // ok - p[(long long unsigned)(p = 0)]; // expected-warning {{unsequenced modification and access to 'p'}} + p[(long long unsigned)(p = 0)]; // cxx11-warning {{unsequenced modification and access to 'p'}} A *q = &agg1; - (q = &agg2)->y = q->x; // expected-warning {{unsequenced modification and access to 'q'}} + (q = &agg2)->y = q->x; // cxx11-warning {{unsequenced modification and access to 'q'}} + // TODO cxx17-warning@-1 {{unsequenced modification and access to 'q'}} // This has undefined behavior if a == 0; otherwise, the side-effect of the // increment is sequenced before the value computation of 'f(a, a)', which is @@ -102,19 +131,326 @@ void test() { (a -= 128) &= 128; // ok ++a += 1; // ok - xs[8] ? ++a + a++ : 0; // expected-warning {{multiple unsequenced modifications}} - xs[8] ? 0 : ++a + a++; // expected-warning {{multiple unsequenced modifications}} + xs[8] ? ++a + a++ : 0; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + xs[8] ? 0 : ++a + a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} xs[8] ? ++a : a++; // ok - xs[8] && (++a + a++); // expected-warning {{multiple unsequenced modifications}} - xs[8] || (++a + a++); // expected-warning {{multiple unsequenced modifications}} + xs[8] && (++a + a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + xs[8] || (++a + a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} (__builtin_classify_type(++a) ? 1 : 0) + ++a; // ok (__builtin_constant_p(++a) ? 1 : 0) + ++a; // ok (__builtin_object_size(&(++a, a), 0) ? 1 : 0) + ++a; // ok - (__builtin_expect(++a, 0) ? 1 : 0) + ++a; // expected-warning {{multiple unsequenced modifications}} + (__builtin_expect(++a, 0) ? 1 : 0) + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} } +namespace members { + +struct S1 { + unsigned bf1 : 2; + unsigned bf2 : 2; + unsigned a; + unsigned b; + static unsigned x; + void member_f(S1 &s); +}; + +void S1::member_f(S1 &s) { + ++a + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + a + ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + ++a + ++b; // no-warning + a + ++b; // no-warning + + // TODO: Warn here. + ++s.a + ++s.a; // no-warning TODO {{multiple unsequenced modifications to}} + s.a + ++s.a; // no-warning TODO {{unsequenced modification and access to}} + ++s.a + ++s.b; // no-warning + s.a + ++s.b; // no-warning + + ++a + ++s.a; // no-warning + a + ++s.a; // no-warning + ++a + ++s.b; // no-warning + a + ++s.b; // no-warning + + // TODO Warn here for bit-fields in the same memory location. + ++bf1 + ++bf1; // cxx11-warning {{multiple unsequenced modifications to 'bf1'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'bf1'}} + bf1 + ++bf1; // cxx11-warning {{unsequenced modification and access to 'bf1'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'bf1'}} + ++bf1 + ++bf2; // no-warning TODO {{multiple unsequenced modifications to}} + bf1 + ++bf2; // no-warning TODO {{unsequenced modification and access to}} + + // TODO Warn here for bit-fields in the same memory location. + ++s.bf1 + ++s.bf1; // no-warning TODO {{multiple unsequenced modifications to}} + s.bf1 + ++s.bf1; // no-warning TODO {{unsequenced modification and access to}} + ++s.bf1 + ++s.bf2; // no-warning TODO {{multiple unsequenced modifications to}} + s.bf1 + ++s.bf2; // no-warning TODO {{unsequenced modification and access to}} + + ++bf1 + ++s.bf1; // no-warning + bf1 + ++s.bf1; // no-warning + ++bf1 + ++s.bf2; // no-warning + bf1 + ++s.bf2; // no-warning + + struct Der : S1 {}; + Der d; + Der &d_ref = d; + S1 &s1_ref = d_ref; + + ++s1_ref.a + ++d_ref.a; // no-warning TODO {{multiple unsequenced modifications to member 'a' of 'd'}} + ++s1_ref.a + d_ref.a; // no-warning TODO {{unsequenced modification and access to member 'a' of 'd'}} + ++s1_ref.a + ++d_ref.b; // no-warning + ++s1_ref.a + d_ref.b; // no-warning + + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++s.x + x; // no-warning TODO {{unsequenced modification and access to static member 'x' of 'S1'}} + ++this->x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++d_ref.x + ++S1::x; // no-warning TODO {{unsequenced modification and access to static member 'x' of 'S1'}} +} + +struct S2 { + union { unsigned x, y; }; + void f2(); +}; + +void S2::f2() { + ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}} + x + ++x; // no-warning TODO {{unsequenced modification and access to}} + ++x + ++y; // no-warning + x + ++y; // no-warning +} + +void f2(S2 &s) { + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning +} + +struct S3 { + union { + union { + unsigned x; + }; + }; + unsigned y; + void f3(); +}; + +void S3::f3() { + ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}} + x + ++x; // no-warning TODO {{unsequenced modification and access to}} + ++x + ++y; // no-warning + x + ++y; // no-warning +} + +void f3(S3 &s) { + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning +} + +struct S4 : S3 { + unsigned y; + void f4(); +}; + +void S4::f4() { + ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}} + x + ++x; // no-warning TODO {{unsequenced modification and access to}} + ++x + ++y; // no-warning + x + ++y; // no-warning + ++S3::y + ++y; // no-warning + S3::y + ++y; // no-warning +} + +void f4(S4 &s) { + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning + ++s.S3::y + ++s.y; // no-warning + s.S3::y + ++s.y; // no-warning +} + +static union { + unsigned Ux; + unsigned Uy; +}; + +void f5() { + ++Ux + ++Ux; // no-warning TODO {{multiple unsequenced modifications to}} + Ux + ++Ux; // no-warning TODO {{unsequenced modification and access to}} + ++Ux + ++Uy; // no-warning + Ux + ++Uy; // no-warning +} + +void f6() { + struct S { unsigned x, y; } s; + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning + + struct { unsigned x, y; } t; + ++t.x + ++t.x; // no-warning TODO {{multiple unsequenced modifications to}} + t.x + ++t.x; // no-warning TODO {{unsequenced modification and access to}} + ++t.x + ++t.y; // no-warning + t.x + ++t.y; // no-warning +} + +} // namespace members + +namespace references { +void reference_f() { + // TODO: Check that we can see through references. + // For now this is completely unhandled. + int a; + int xs[10]; + int &b = a; + int &c = b; + int &ra1 = c; + int &ra2 = b; + int other; + + ++ra1 + ++ra2; // no-warning TODO {{multiple unsequenced modifications to}} + ra1 + ++ra2; // no-warning TODO {{unsequenced modification and access to}} + ++ra1 + ++other; // no-warning + ra1 + ++other; // no-warning + + // Make sure we handle reference cycles. + int &ref_cycle = ref_cycle; + ++ref_cycle + ++ref_cycle; // cxx11-warning {{multiple unsequenced modifications to 'ref_cycle'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'ref_cycle'}} + ref_cycle + ++ref_cycle; // cxx11-warning {{unsequenced modification and access to 'ref_cycle'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'ref_cycle'}} +} +} // namespace references + +namespace std { + using size_t = decltype(sizeof(0)); + template<typename> struct tuple_size; + template<size_t, typename> struct tuple_element { using type = int; }; +} +namespace bindings { + + struct A { int x, y; }; + typedef int B[2]; + struct C { template<int> int get(); }; + struct D : A {}; + +} // namespace bindings +template<> struct std::tuple_size<bindings::C> { enum { value = 2 }; }; +namespace bindings { +void testa() { + A a; + { + auto [x, y] = a; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + ++x + ++a.x; // no-warning + ++x + a.x; // no-warning + } + { + auto &[x, y] = a; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + ++x + ++a.x; // no-warning TODO + ++x + a.x; // no-warning TODO + } +} +void testb() { + B b; + { + auto [x, y] = b; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + ++x + ++b[0]; // no-warning + ++x + b[0]; // no-warning + } + { + auto &[x, y] = b; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + ++x + ++b[0]; // no-warning TODO + ++x + b[0]; // no-warning TODO + } +} +void testc() { + C c; + { + auto [x, y] = c; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + } + { + auto &[x, y] = c; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + } +} +void testd() { + D d; + { + auto [x, y] = d; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + ++x + ++d.x; // no-warning + ++x + d.x; // no-warning + } + { + auto &[x, y] = d; + ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}} + ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'x'}} + ++x + ++y; // no-warning + ++x + y; // no-warning + ++x + ++d.x; // no-warning TODO + ++x + d.x; // no-warning TODO + } +} +} // namespace bindings + namespace templates { template <typename T> @@ -146,26 +482,42 @@ int Foo<X>::Run() { if (static_cast<E>((num = bar.get()) < 5) || static_cast<E>(num < 10)) { } if (static_cast<E>((num = bar.get()) < 5) && static_cast<E>(num < 10)) { } - // expected-warning@-1 {{unsequenced modification and access to 'num'}} + // cxx11-warning@-1 {{unsequenced modification and access to 'num'}} + // cxx17-warning@-2 {{unsequenced modification and access to 'num'}} foo(num++, num++); - // expected-warning@-1 2{{multiple unsequenced modifications to 'num'}} + // cxx11-warning@-1 {{multiple unsequenced modifications to 'num'}} + // cxx17-warning@-2 {{multiple unsequenced modifications to 'num'}} return 1; } int x = Foo<int>().Run(); -// expected-note@-1 {{in instantiation of member function 'templates::Foo<int>::Run'}} +// cxx11-note@-1 {{in instantiation of member function 'templates::Foo<int>::Run'}} +// cxx17-note@-2 {{in instantiation of member function 'templates::Foo<int>::Run'}} template <typename T> int Run2() { T t = static_cast<T>(0); return (t = static_cast<T>(1)) && t; - // expected-warning@-1 {{unsequenced modification and access to 't'}} + // cxx11-warning@-1 {{unsequenced modification and access to 't'}} + // cxx17-warning@-2 {{unsequenced modification and access to 't'}} } int y = Run2<bool>(); int z = Run2<E>(); -// expected-note@-1{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}} - +// cxx11-note@-1{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}} +// cxx17-note@-2{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}} + +template <typename T> int var = sizeof(T); +void test_var() { + var<int>++ + var<int>++; // cxx11-warning {{multiple unsequenced modifications to 'var<int>'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'var<int>'}} + var<int>++ + var<int>; // cxx11-warning {{unsequenced modification and access to 'var<int>'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'var<int>'}} + int &r = var<int>; + r++ + var<int>++; // no-warning TODO {{multiple unsequenced modifications to 'var<int>'}} + r++ + var<long>++; // no-warning } + +} // namespace templates diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp index 93c6bbd7ed..e052ecb1af 100644 --- a/test/SemaCXX/warn-unused-filescoped.cpp +++ b/test/SemaCXX/warn-unused-filescoped.cpp @@ -207,8 +207,9 @@ static void completeRedeclChainForTemplateSpecialization() { } // expected-warni namespace test10 { #if __cplusplus >= 201103L +// FIXME: Warn on template definitions with no instantiations? template<class T> -constexpr T pi = T(3.14); // expected-warning {{unused}} +constexpr T pi = T(3.14); #endif } diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index a7ac9afc36..97634ac43c 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -135,7 +135,9 @@ namespace PR19305 { template<typename T> int m = 0; template<typename T> int m<T*> = 0; - template<> const int m<void> = 0; // expected-warning {{unused variable}} + // This has external linkage, so could be referenced by a declaration in a + // different translation unit. + template<> const int m<void> = 0; // no warning } namespace ctor_with_cleanups { |