diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /test/SemaCXX | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) |
Notes
Diffstat (limited to 'test/SemaCXX')
95 files changed, 2983 insertions, 742 deletions
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp index 203a810111426..727e67528fa0b 100644 --- a/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -302,3 +302,23 @@ void function_to_voidptr_conv() { void *a2 = &function_prototype; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} void *a3 = function_ptr; // expected-warning {{implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension}} } + +namespace member_lookup { + +template<typename T> +struct ConfuseLookup { + T* m_val; + struct m_val { + static size_t ms_test; + }; +}; + +// Microsoft mode allows explicit constructor calls +// This could confuse name lookup in cases such as this +template<typename T> +size_t ConfuseLookup<T>::m_val::ms_test + = size_t(&(char&)(reinterpret_cast<ConfuseLookup<T>*>(0)->m_val)); + +void instantiate() { ConfuseLookup<int>::m_val::ms_test = 1; } +} + diff --git a/test/SemaCXX/PR38913.cpp b/test/SemaCXX/PR38913.cpp new file mode 100644 index 0000000000000..698de8c84411e --- /dev/null +++ b/test/SemaCXX/PR38913.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// PR38913 +// Check that we instantiate attributes on declarations for... + +// ...a member class of a class template specialization +template<class T> struct A { struct __attribute__((abi_tag("ATAG"))) X { }; }; +A<int>::X* a() { return 0; } // CHECK-DAG: @_Z1aB4ATAGv + +// ...a member class template +template<class T> struct B { template<class U> struct __attribute__((abi_tag("BTAG"))) X { }; }; +B<int>::X<int>* b() { return 0; } // CHECK-DAG: @_Z1bB4BTAGv diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp index cca847b4d2c32..6b6734bae17d2 100644 --- a/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -221,13 +221,13 @@ namespace test1 { void QualifierTest() { void (Qualifiers::*X)(); - X = &Qualifiers::C; // expected-error-re {{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (none vs const)}} - X = &Qualifiers::V; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (none vs volatile)}} - X = &Qualifiers::R; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (none vs restrict)}} - X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (none vs const and volatile)}} - X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (none vs const and restrict)}} - X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (none vs volatile and restrict)}} - X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (none vs const, volatile, and restrict)}} + X = &Qualifiers::C; // expected-error-re {{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': different qualifiers (unqualified vs 'const')}} + X = &Qualifiers::V; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': different qualifiers (unqualified vs 'volatile')}} + X = &Qualifiers::R; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': different qualifiers (unqualified vs '__restrict')}} + X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': different qualifiers (unqualified vs 'const volatile')}} + X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': different qualifiers (unqualified vs 'const __restrict')}} + X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': different qualifiers (unqualified vs 'volatile __restrict')}} + X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': different qualifiers (unqualified vs 'const volatile __restrict')}} } struct Dummy { diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index 0dfb61333ec28..bb03c6fb5cf14 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -186,3 +186,51 @@ namespace HugeArraysUseArrayFiller { // amount of time. struct A { int n; int arr[1000 * 1000 * 1000]; } a = {1, {2}}; } + +namespace ElementDestructor { + // The destructor for each element of class type is potentially invoked + // (15.4 [class.dtor]) from the context where the aggregate initialization + // occurs. Produce a diagnostic if an element's destructor isn't accessible. + + class X { int f; ~X(); }; // expected-note {{implicitly declared private here}} + struct Y { X x; }; + + void test0() { + auto *y = new Y {}; // expected-error {{temporary of type 'ElementDestructor::X' has private destructor}} + } + + struct S0 { int f; ~S0() = delete; }; // expected-note 3 {{'~S0' has been explicitly marked deleted here}} + struct S1 { S0 s0; int f; }; + + S1 test1() { + auto *t = new S1 { .f = 1 }; // expected-error {{attempt to use a deleted function}} + return {2}; // expected-error {{attempt to use a deleted function}} + } + + // Check if the type of an array element has a destructor. + struct S2 { S0 a[4]; }; + + void test2() { + auto *t = new S2 {1,2,3,4}; // expected-error {{attempt to use a deleted function}} + } + +#if __cplusplus >= 201703L + namespace BaseDestructor { + struct S0 { int f; ~S0() = delete; }; // expected-note {{'~S0' has been explicitly marked deleted here}} + + // Check destructor of base class. + struct S3 : S0 {}; + + void test3() { + S3 s3 = {1}; // expected-error {{attempt to use a deleted function}} + } + } +#endif + + // A's destructor doesn't have to be accessible from the context of C's + // initialization. + struct A { friend struct B; private: ~A(); }; + struct B { B(); A a; }; + struct C { B b; }; + C c = { B() }; +} diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index b6256103ef8d2..0a92b9dd96392 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/test/SemaCXX/alias-template.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++14 -fcxx-exceptions %s namespace RedeclAliasTypedef { template<typename U> using T = int; @@ -179,3 +179,17 @@ struct S { }; static_assert(__is_same(S<3>::U, X[2]), ""); // expected-error {{static_assert failed}} } + +namespace PR39623 { +template <class T> +using void_t = void; + +template <class T, class = void_t<typename T::wait_what>> +int sfinae_me() { return 0; } // expected-note{{candidate template ignored: substitution failure}} + +int g = sfinae_me<int>(); // expected-error{{no matching function for call to 'sfinae_me'}} +} + +namespace NullExceptionDecl { +template<int... I> auto get = []() { try { } catch(...) {}; return I; }; // expected-error{{initializer contains unexpanded parameter pack 'I'}} +} diff --git a/test/SemaCXX/align-x86-abi7.cpp b/test/SemaCXX/align-x86-abi7.cpp new file mode 100644 index 0000000000000..3088a13f78577 --- /dev/null +++ b/test/SemaCXX/align-x86-abi7.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++11 -triple i386-apple-darwin9 -fsyntax-only -verify -fclang-abi-compat=7 %s +// expected-no-diagnostics + +using size_t = decltype(sizeof(0)); + +template <typename T, size_t Preferred> +struct check_alignment { + using type = T; + static type value; + + static_assert(__alignof__(value) == Preferred, "__alignof__(value) != Preferred"); + static_assert(__alignof__(type) == Preferred, "__alignof__(type) != Preferred"); + static_assert(alignof(type) == Preferred, "alignof(type) != Preferred"); +}; + +// PR3433 +template struct check_alignment<double, 8>; +template struct check_alignment<long long, 8>; +template struct check_alignment<unsigned long long, 8>; + +// PR6362 +template struct check_alignment<double[3], 8>; + +enum big_enum { x = 18446744073709551615ULL }; +template struct check_alignment<big_enum, 8>; diff --git a/test/SemaCXX/align-x86.cpp b/test/SemaCXX/align-x86.cpp new file mode 100644 index 0000000000000..0c97fc28fe5fd --- /dev/null +++ b/test/SemaCXX/align-x86.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++11 -triple i386-apple-darwin9 -fsyntax-only -verify %s +// expected-no-diagnostics + +using size_t = decltype(sizeof(0)); + +struct complex_double { + double real; + double imag; +}; + +template <typename T, size_t ABI, size_t Preferred> +struct check_alignment { + using type = T; + static type value; + + static_assert(__alignof__(value) == Preferred, "__alignof__(value) != Preferred"); + static_assert(__alignof__(type) == Preferred, "__alignof__(type) != Preferred"); + static_assert(alignof(type) == ABI, "alignof(type) != ABI"); +}; + +// PR3433 +template struct check_alignment<double, 4, 8>; +template struct check_alignment<long long, 4, 8>; +template struct check_alignment<unsigned long long, 4, 8>; +template struct check_alignment<complex_double, 4, 4>; + +// PR6362 +struct __attribute__((packed)) +packed_struct { + unsigned int a; +} g_packedstruct; +template struct check_alignment<packed_struct, 1, 1>; +static_assert(__alignof__(g_packedstruct.a) == 1, "__alignof__(packed_struct.member) != 1"); + +template struct check_alignment<double[3], 4, 8>; + +enum big_enum { x = 18446744073709551615ULL }; +template struct check_alignment<big_enum, 4, 8>; + +// PR5637 + +#define ALIGNED(x) __attribute__((aligned(x))) + +typedef ALIGNED(2) struct { + char a[3]; +} aligned_before_struct; + +static_assert(sizeof(aligned_before_struct) == 3, ""); +static_assert(sizeof(aligned_before_struct[1]) == 4, ""); +static_assert(sizeof(aligned_before_struct[2]) == 6, ""); +static_assert(sizeof(aligned_before_struct[2][1]) == 8, ""); +static_assert(sizeof(aligned_before_struct[1][2]) == 6, ""); + +typedef struct ALIGNED(2) { + char a[3]; +} aligned_after_struct; + +static_assert(sizeof(aligned_after_struct) == 4, ""); +static_assert(sizeof(aligned_after_struct[1]) == 4, ""); +static_assert(sizeof(aligned_after_struct[2]) == 8, ""); +static_assert(sizeof(aligned_after_struct[2][1]) == 8, ""); +static_assert(sizeof(aligned_after_struct[1][2]) == 8, ""); diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp index e3690ea926a25..f2854024da1ac 100644 --- a/test/SemaCXX/alignof.cpp +++ b/test/SemaCXX/alignof.cpp @@ -11,7 +11,7 @@ struct S0 { struct S1; // expected-note 6 {{forward declaration}} extern S1 s1; -const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} +const int test3 = __alignof__(s1); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}} struct S2 { S2(); @@ -19,11 +19,11 @@ struct S2 { int x; int test4 = __alignof__(x); // ok - int test5 = __alignof__(s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + int test5 = __alignof__(s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}} }; const int test6 = __alignof__(S2::x); -const int test7 = __alignof__(S2::s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} +const int test7 = __alignof__(S2::s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}} // Arguably, these should fail like the S1 cases do: the alignment of // 's2.x' should depend on the alignment of both x-within-S2 and @@ -34,10 +34,10 @@ struct S3 { S2 s2; static const int test8 = __alignof__(s2.x); - static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}} auto test10() -> char(&)[__alignof__(s2.x)]; static const int test11 = __alignof__(S3::s2.x); - static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of '__alignof' to an incomplete type 'S1'}} auto test13() -> char(&)[__alignof__(s2.x)]; }; @@ -59,9 +59,9 @@ struct S5 { }; const int test8 = __alignof__(S5::x); -long long int test14[2]; +int test14[2]; -static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}} +static_assert(alignof(test14) == 4, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}} // PR19992 static_assert(alignof(int[]) == alignof(int), ""); // ok @@ -97,3 +97,8 @@ struct S { typedef __attribute__((aligned(N))) int Field[sizeof(N)]; // expected-error {{requested alignment is dependent but declaration is not dependent}} }; } + +typedef int __attribute__((aligned(16))) aligned_int; +template <typename> +using template_alias = aligned_int; +static_assert(alignof(template_alias<void>) == 16, "Expected alignment of 16" ); diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp index a97f8e312a05d..6ebff8c992068 100644 --- a/test/SemaCXX/array-bounds.cpp +++ b/test/SemaCXX/array-bounds.cpp @@ -284,3 +284,15 @@ struct multi_s multi2[4]; // expected-note {{array 'multi2' declared here}} int test_struct_multiarray() { return multi2[4].arr[0]; // expected-warning {{array index 4 is past the end of the array (which contains 4 elements)}} } + +namespace PR39746 { + struct S; + extern S xxx[2]; // expected-note {{array 'xxx' declared here}} + class C {}; + + C &f() { return reinterpret_cast<C *>(xxx)[1]; } // no-warning + // We have no info on whether this is out-of-bounds. + C &g() { return reinterpret_cast<C *>(xxx)[2]; } // no-warning + // 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}} +} diff --git a/test/SemaCXX/attr-cpuspecific.cpp b/test/SemaCXX/attr-cpuspecific.cpp index a881b6c4e2bae..7ec8c6cd0ce2c 100644 --- a/test/SemaCXX/attr-cpuspecific.cpp +++ b/test/SemaCXX/attr-cpuspecific.cpp @@ -109,3 +109,6 @@ int __attribute__((cpu_specific(sandybridge))) BadOutOfLine::foo(int) { return 1 // Ensure Cpp Spelling works. [[clang::cpu_specific(ivybridge,atom)]] int CppSpelling(){} + +// expected-error@+1 {{lambda cannot be declared 'cpu_dispatch'}} +auto x = []() __attribute__((cpu_dispatch(atom))) {}; diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp new file mode 100644 index 0000000000000..24e24221939fa --- /dev/null +++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -Wundefined-func-template -Wundefined-var-template -verify %s + +// Test that a diagnostic is emitted when an entity marked with the +// exclude_from_explicit_instantiation attribute is not defined in +// the current TU but it is used (and it is hence implicitly +// instantiated). + +#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) + +template <class T> +struct Foo { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function(); // expected-note{{forward declaration of template entity is here}} + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function(); // expected-note{{forward declaration of template entity is here}} + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member; // expected-note{{forward declaration of template entity is here}} + struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION nested { + static int static_member_function(); // expected-note{{forward declaration of template entity is here}} + }; +}; + +extern template struct Foo<int>; + +void use() { + Foo<int> foo; + + foo.non_static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::non_static_member_function' required here, but no definition is available}} + // expected-note@-1 {{add an explicit instantiation}} + + Foo<int>::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::static_member_function' required here, but no definition is available}} + // expected-note@-1 {{add an explicit instantiation}} + + (void)Foo<int>::static_data_member; // expected-warning{{instantiation of variable 'Foo<int>::static_data_member' required here, but no definition is available}} + // expected-note@-1 {{add an explicit instantiation}} + + Foo<int>::nested::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::nested::static_member_function' required here, but no definition is available}} + // expected-note@-1 {{add an explicit instantiation}} +} diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp new file mode 100644 index 0000000000000..379ab0a3eb00e --- /dev/null +++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test that explicit instantiations do not instantiate entities +// marked with the exclude_from_explicit_instantiation attribute. + +#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) + +template <class T> +struct Foo { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member; + + struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 { + static void non_static_member_function() { using Fail = typename T::fail; } + }; + + struct member_class2 { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void non_static_member_function() { using Fail = typename T::fail; } + }; +}; + +template <class T> +inline void Foo<T>::non_static_member_function1() { using Fail = typename T::fail; } + +template <class T> +void Foo<T>::non_static_member_function2() { using Fail = typename T::fail; } + +template <class T> +inline void Foo<T>::static_member_function1() { using Fail = typename T::fail; } + +template <class T> +void Foo<T>::static_member_function2() { using Fail = typename T::fail; } + +template <class T> +int Foo<T>::static_data_member = T::fail; + +// expected-no-diagnostics +template struct Foo<int>; diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp new file mode 100644 index 0000000000000..4cb02252ba350 --- /dev/null +++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -Wno-unused-local-typedef -fsyntax-only -verify %s + +// Test that extern instantiation declarations cause members marked with +// the exclude_from_explicit_instantiation attribute to be instantiated in +// the current TU. + +#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) + +template <class T> +struct Foo { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2(); + + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member; + + struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 { + static void static_member_function() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} + } + }; + + struct member_class2 { + EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} + } + }; +}; + +template <class T> +inline void Foo<T>::non_static_member_function1() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template <class T> +void Foo<T>::non_static_member_function2() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template <class T> +inline void Foo<T>::static_member_function1() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template <class T> +void Foo<T>::static_member_function2() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template <class T> +int Foo<T>::static_data_member = T::invalid; // expected-error{{no member named 'invalid' in 'Empty'}} + +struct Empty { }; +extern template struct Foo<Empty>; + +int main() { + Foo<Empty> foo; + foo.non_static_member_function1(); // expected-note{{in instantiation of}} + foo.non_static_member_function2(); // expected-note{{in instantiation of}} + Foo<Empty>::static_member_function1(); // expected-note{{in instantiation of}} + Foo<Empty>::static_member_function2(); // expected-note{{in instantiation of}} + (void)foo.static_data_member; // expected-note{{in instantiation of}} + Foo<Empty>::member_class1::static_member_function(); // expected-note{{in instantiation of}} + Foo<Empty>::member_class2::static_member_function(); // expected-note{{in instantiation of}} +} diff --git a/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp b/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp new file mode 100644 index 0000000000000..da861ab972358 --- /dev/null +++ b/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test that we properly merge the exclude_from_explicit_instantiation +// attribute on redeclarations. + +#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) + +template <class T> +struct Foo { + // Declaration without the attribute, definition with the attribute. + void func1(); + + // Declaration with the attribute, definition without the attribute. + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func2(); + + // Declaration with the attribute, definition with the attribute. + EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func3(); +}; + +template <class T> +EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func1() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template <class T> +void Foo<T>::func2() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +template <class T> +EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func3() { + using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} +} + +struct Empty { }; +extern template struct Foo<Empty>; + +int main() { + Foo<Empty> foo; + foo.func1(); // expected-note{{in instantiation of}} + foo.func2(); // expected-note{{in instantiation of}} + foo.func3(); // expected-note{{in instantiation of}} +} diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp index a553f0d210003..9eb42342df31a 100644 --- a/test/SemaCXX/attr-gnu.cpp +++ b/test/SemaCXX/attr-gnu.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -fms-compatibility -verify %s - -void f() { - // GNU-style attributes are prohibited in this position. +// RUN: %clang_cc1 -std=gnu++17 -fsyntax-only -fms-compatibility -verify %s
+
+void f() {
+ // GNU-style attributes are prohibited in this position.
auto P = new int * __attribute__((vector_size(8))); // expected-error {{an attribute list cannot appear here}} \ // expected-error {{invalid vector element type 'int *'}} @@ -40,6 +40,13 @@ void tuTest1(Tu<int> u); // expected-note {{candidate function not viable: no kn void tuTest2(Tu3 u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu3' for 1st argument}} void tu() { int x = 2; - tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}} - tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}} -} + tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
+ tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
+}
+
+[[gnu::__const__]] int f2() { return 12; }
+[[__gnu__::__const__]] int f3() { return 12; }
+[[using __gnu__ : __const__]] int f4() { return 12; }
+
+static_assert(__has_cpp_attribute(gnu::__const__));
+static_assert(__has_cpp_attribute(__gnu__::__const__));
diff --git a/test/SemaCXX/attr-on-explicit-template-instantiation.cpp b/test/SemaCXX/attr-on-explicit-template-instantiation.cpp new file mode 100644 index 0000000000000..ddb9c8e2e4a53 --- /dev/null +++ b/test/SemaCXX/attr-on-explicit-template-instantiation.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s + +// PR39118 +// Make sure that attributes are properly applied to explicit template +// instantiations. + +#define HIDDEN __attribute__((__visibility__("hidden"))) +#define VISIBLE __attribute__((__visibility__("default"))) + +namespace ns HIDDEN { + struct A { }; + template <typename T> struct B { static A a; }; + template <typename T> A B<T>::a; + + // CHECK: @_ZN2ns1BIiE1aE = weak_odr global + // CHECK-NOT: hidden + template VISIBLE A B<int>::a; +} + +struct C { }; +template <typename T> struct D { static C c; }; +template <typename T> C D<T>::c; + +// CHECK-DAG: @_ZN1DIiE1cB3TAGE +template __attribute__((abi_tag("TAG"))) C D<int>::c; diff --git a/test/SemaCXX/attr-optnone.cpp b/test/SemaCXX/attr-optnone.cpp index 58776caf7ae60..c8e85eec37116 100644 --- a/test/SemaCXX/attr-optnone.cpp +++ b/test/SemaCXX/attr-optnone.cpp @@ -71,3 +71,11 @@ struct B2 { static void bar(); }; +// Verify that we can handle the [[_Clang::optnone]] and +// [[__clang__::optnone]] spellings, as well as [[clang::__optnone__]]. +[[_Clang::optnone]] int foo3(); +[[__clang__::optnone]] int foo4(); // expected-warning {{'__clang__' is a predefined macro name, not an attribute scope specifier; did you mean '_Clang' instead?}} +[[clang::__optnone__]] int foo5(); +[[_Clang::__optnone__]] int foo6(); + +[[_Clang::optnone]] int foo7; // expected-warning {{'optnone' attribute only applies to functions}} diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp index 960050bc7106a..d7ef42306bd39 100644 --- a/test/SemaCXX/attr-print.cpp +++ b/test/SemaCXX/attr-print.cpp @@ -13,8 +13,8 @@ void foo() __attribute__((const)); // CHECK: void bar() __attribute__((__const)); void bar() __attribute__((__const)); -// FIXME: Print this with correct format and order. -// CHECK: void foo1() __attribute__((pure)) __attribute__((noinline)); +// FIXME: Print this with correct format. +// CHECK: void foo1() __attribute__((noinline)) __attribute__((pure)); void foo1() __attribute__((noinline, pure)); // CHECK: typedef int Small1 __attribute__((mode(byte))); diff --git a/test/SemaCXX/attr-reinitializes.cpp b/test/SemaCXX/attr-reinitializes.cpp new file mode 100644 index 0000000000000..129d359b8b742 --- /dev/null +++ b/test/SemaCXX/attr-reinitializes.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +[[clang::reinitializes]] int a; // expected-error {{'reinitializes' attribute only applies to non-static non-const member functions}} + +[[clang::reinitializes]] void f(); // expected-error {{only applies to}} + +struct A { + [[clang::reinitializes]] void foo(); + __attribute__((reinitializes)) void gnu_foo(); + [[clang::reinitializes]] void bar() const; // expected-error {{only applies to}} + [[clang::reinitializes]] static void baz(); // expected-error {{only applies to}} + [[clang::reinitializes]] int a; // expected-error {{only applies to}} + + [[clang::reinitializes("arg")]] void qux(); // expected-error {{'reinitializes' attribute takes no arguments}} +}; diff --git a/test/SemaCXX/attr-speculative-load-hardening.cpp b/test/SemaCXX/attr-speculative-load-hardening.cpp new file mode 100644 index 0000000000000..bba3b6921e8d8 --- /dev/null +++ b/test/SemaCXX/attr-speculative-load-hardening.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int i __attribute__((speculative_load_hardening)); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +void f1() __attribute__((speculative_load_hardening)); +void f2() __attribute__((speculative_load_hardening(1))); // expected-error {{'speculative_load_hardening' attribute takes no arguments}} + +template <typename T> +void tf1() __attribute__((speculative_load_hardening)); + +int f3(int __attribute__((speculative_load_hardening)), int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +struct A { + int f __attribute__((speculative_load_hardening)); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + void mf1() __attribute__((speculative_load_hardening)); + static void mf2() __attribute__((speculative_load_hardening)); +}; + +int ci [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +[[clang::speculative_load_hardening]] void cf1(); +[[clang::speculative_load_hardening(1)]] void cf2(); // expected-error {{'speculative_load_hardening' attribute takes no arguments}} + +template <typename T> +[[clang::speculative_load_hardening]] +void ctf1(); + +int cf3(int c[[clang::speculative_load_hardening]], int); // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + +struct CA { + int f [[clang::speculative_load_hardening]]; // expected-error {{'speculative_load_hardening' attribute only applies to functions}} + [[clang::speculative_load_hardening]] void mf1(); + [[clang::speculative_load_hardening]] static void mf2(); +}; diff --git a/test/SemaCXX/auto-pragma.cpp b/test/SemaCXX/auto-pragma.cpp deleted file mode 100644 index 1cd0781fe9a7a..0000000000000 --- a/test/SemaCXX/auto-pragma.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -ast-dump -ast-dump-filter AutoVar | FileCheck %s - -namespace { - class foo { - }; -} - -#pragma GCC visibility push(hidden) -auto AutoVar = foo(); - -// CHECK: VarDecl {{.*}} AutoVar -// CHECK-NOT: VisibilityAttr diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp index f26931b55bdb0..fbe2c457dad97 100644 --- a/test/SemaCXX/builtins.cpp +++ b/test/SemaCXX/builtins.cpp @@ -53,3 +53,95 @@ extern "C" int vfprintf(FILE *__restrict, const char *__restrict, void synchronize_args() { __sync_synchronize(0); // expected-error {{too many arguments}} } + +namespace test_launder { +#define TEST_TYPE(Ptr, Type) \ + static_assert(__is_same(decltype(__builtin_launder(Ptr)), Type), "expected same type") + +struct Dummy {}; + +using FnType = int(char); +using MemFnType = int (Dummy::*)(char); +using ConstMemFnType = int (Dummy::*)() const; + +void foo() {} + +void test_builtin_launder_diags(void *vp, const void *cvp, FnType *fnp, + MemFnType mfp, ConstMemFnType cmfp, int (&Arr)[5]) { + __builtin_launder(vp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}} + __builtin_launder(cvp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}} + __builtin_launder(fnp); // expected-error {{function pointer argument to '__builtin_launder' is not allowed}} + __builtin_launder(mfp); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}} + __builtin_launder(cmfp); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}} + (void)__builtin_launder(&fnp); + __builtin_launder(42); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}} + __builtin_launder(nullptr); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}} + __builtin_launder(foo); // expected-error {{function pointer argument to '__builtin_launder' is not allowed}} + (void)__builtin_launder(Arr); +} + +void test_builtin_launder(char *p, const volatile int *ip, const float *&fp, + double *__restrict dp) { + int x; + __builtin_launder(x); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}} + + TEST_TYPE(p, char*); + TEST_TYPE(ip, const volatile int*); + TEST_TYPE(fp, const float*); + TEST_TYPE(dp, double *__restrict); + + char *d = __builtin_launder(p); + const volatile int *id = __builtin_launder(ip); + int *id2 = __builtin_launder(ip); // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const volatile int *'}} + const float* fd = __builtin_launder(fp); +} + +void test_launder_return_type(const int (&ArrayRef)[101], int (&MArrRef)[42][13], + void (**&FuncPtrRef)()) { + TEST_TYPE(ArrayRef, const int *); + TEST_TYPE(MArrRef, int(*)[13]); + TEST_TYPE(FuncPtrRef, void (**)()); +} + +template <class Tp> +constexpr Tp *test_constexpr_launder(Tp *tp) { + return __builtin_launder(tp); +} +constexpr int const_int = 42; +constexpr int const_int2 = 101; +constexpr const int *const_ptr = test_constexpr_launder(&const_int); +static_assert(&const_int == const_ptr, ""); +static_assert(const_ptr != test_constexpr_launder(&const_int2), ""); + +void test_non_constexpr() { + constexpr int i = 42; // expected-note {{declared here}} + constexpr const int *ip = __builtin_launder(&i); // expected-error {{constexpr variable 'ip' must be initialized by a constant expression}} + // expected-note@-1 {{pointer to 'i' is not a constant expression}} +} + +constexpr bool test_in_constexpr(const int &i) { + return (__builtin_launder(&i) == &i); +} + +static_assert(test_in_constexpr(const_int), ""); +void f() { + constexpr int i = 42; + static_assert(test_in_constexpr(i), ""); +} + +struct Incomplete; // expected-note {{forward declaration}} +struct IncompleteMember { + Incomplete &i; +}; +void test_incomplete(Incomplete *i, IncompleteMember *im) { + // expected-error@+1 {{incomplete type 'test_launder::Incomplete' where a complete type is required}} + __builtin_launder(i); + __builtin_launder(&i); // OK + __builtin_launder(im); // OK +} + +void test_noexcept(int *i) { + static_assert(noexcept(__builtin_launder(i)), ""); +} +#undef TEST_TYPE +} // end namespace test_launder diff --git a/test/SemaCXX/calling-conv-compat.cpp b/test/SemaCXX/calling-conv-compat.cpp index 4c4cc15f165ac..a268d9da07ee5 100644 --- a/test/SemaCXX/calling-conv-compat.cpp +++ b/test/SemaCXX/calling-conv-compat.cpp @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple i686-pc-win32 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify -triple x86_64-pc-win32 %s + +// FIXME: Extend this portion of the test to cover the 64-bit case. +#if !_M_X64 // Pointers to free functions void free_func_default(); @@ -244,11 +248,16 @@ void call_member_inheritance() { } } // end namespace NonVariadic +#endif // !_M_X64 + namespace Variadic { struct A { void member_default(int, ...); void __cdecl member_cdecl(int, ...); - void __thiscall member_thiscall(int, ...); // expected-error {{variadic function cannot use thiscall calling convention}} + void __thiscall member_thiscall(int, ...); +#if !_M_X64 + // expected-error@-2 {{variadic function cannot use thiscall calling convention}} +#endif }; struct B : public A { @@ -319,7 +328,10 @@ mptr_t __stdcall return_mptr_std(short) { } void (A::*(*return_fptr_std_mptr(char))(short))(int) { - return return_mptr_std; // expected-error {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}} + return return_mptr_std; +#if !_M_X64 + // expected-error@-2 {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}} +#endif } void call_return() { @@ -387,15 +399,32 @@ Y<decltype(&A::method_thiscall)>::p tmpl9 = &f_cdecl; // Test that lambdas that capture nothing convert to cdecl function pointers. namespace Lambdas { - void pass_fptr_cdecl (void (__cdecl *fp)()); -void pass_fptr_stdcall (void (__stdcall *fp)()); // expected-note {{candidate function not viable}} -void pass_fptr_fastcall(void (__fastcall *fp)()); // expected-note {{candidate function not viable}} +void pass_fptr_stdcall (void (__stdcall *fp)()); +void pass_fptr_fastcall(void (__fastcall *fp)()); void conversion_to_fptr() { pass_fptr_cdecl ([]() { } ); - pass_fptr_stdcall ([]() { } ); // expected-error {{no matching function for call}} - pass_fptr_fastcall([]() { } ); // expected-error {{no matching function for call}} + + pass_fptr_stdcall ([]() { } ); +#if !_M_X64 + // expected-error@-2 {{no matching function for call}} + // expected-note@-9 {{candidate function not viable}} +#endif + + pass_fptr_fastcall([]() { } ); +#if !_M_X64 + // expected-error@-2 {{no matching function for call}} + // expected-note@-14 {{candidate function not viable}} +#endif +} } +namespace D50526 { + template<typename T, T (__stdcall f)()> void g(); + void h() { g<void, h>(); } +#if !_M_X64 + // expected-error@-2 {{no matching function for call to}} + // expected-note@-4 {{invalid explicitly-specified argument}} +#endif } diff --git a/test/SemaCXX/char8_t.cpp b/test/SemaCXX/char8_t.cpp index 5eb3d7062d2c2..f60a66dbe84de 100644 --- a/test/SemaCXX/char8_t.cpp +++ b/test/SemaCXX/char8_t.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fchar8_t -std=c++2a -verify %s +// RUN: %clang_cc1 -fchar8_t -std=c++17 -verify %s +// RUN: %clang_cc1 -std=c++2a -verify %s char8_t a = u8'a'; char8_t b[] = u8"foo"; @@ -6,7 +7,12 @@ char8_t c = 'a'; char8_t d[] = "foo"; // expected-error {{initializing 'char8_t' array with plain string literal}} expected-note {{add 'u8' prefix}} char e = u8'a'; -char f[] = u8"foo"; // expected-error {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}} +char f[] = u8"foo"; +#if __cplusplus <= 201703L +// expected-error@-2 {{initialization of char array with UTF-8 string literal is not permitted by '-fchar8_t'}} +#else +// expected-error@-4 {{ISO C++20 does not permit initialization of char array with UTF-8 string literal}} +#endif char g = 'a'; char h[] = "foo"; diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp index be9ebee00c2fb..353be2cf48e4f 100644 --- a/test/SemaCXX/compound-literal.cpp +++ b/test/SemaCXX/compound-literal.cpp @@ -34,9 +34,19 @@ namespace brace_initializers { ~HasCtorDtor();
};
+ POD p = (POD){1, 2};
+ // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
+ // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NEXT: ConstantExpr {{.*}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: ConstantExpr {{.*}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
void test() {
(void)(POD){1, 2};
// CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
+ // CHECK-NOT: ConstantExpr {{.*}} 'brace_initializers::POD'
// CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
@@ -52,6 +62,7 @@ namespace brace_initializers { #if __cplusplus >= 201103L
(void)(HasCtor){1, 2};
// CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtor'
+ // CHECK-CXX11-NOT: ConstantExpr {{.*}} 'brace_initializers::HasCtor'
// CHECK-CXX11: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtor'
// CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtor'
// CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
@@ -59,7 +70,8 @@ namespace brace_initializers { (void)(HasCtorDtor){1, 2};
// CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtorDtor'
- // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NOT: ConstantExpr {{.*}} 'brace_initializers::HasCtorDtor'
+ // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtorDtor'
// CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtorDtor'
// CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
// CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index a64207583dd55..578a057104a32 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -253,7 +253,7 @@ namespace FunctionPointers { static_assert(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, ""); - constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(0, 0)'}} + constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(nullptr, 0)'}} } @@ -1972,9 +1972,9 @@ namespace ZeroSizeTypes { namespace BadDefaultInit { template<int N> struct X { static const int n = N; }; - struct A { + struct A { // expected-error {{default member initializer for 'k' needed within definition of enclosing class}} int k = // expected-note {{default member initializer declared here}} - X<A().k>::n; // expected-error {{default member initializer for 'k' needed within definition of enclosing class}} + X<A().k>::n; // expected-note {{in evaluation of exception specification for 'BadDefaultInit::A::A' needed here}} }; // FIXME: The "constexpr constructor must initialize all members" diagnostic diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp index 00df2e5c77a41..3c57ac573f2cb 100644 --- a/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/test/SemaCXX/constant-expression-cxx1y.cpp @@ -356,6 +356,14 @@ namespace compound_assign { if (a != 13) return false; a &= 14; if (a != 12) return false; + a += -1.2; + if (a != 10) return false; + a -= 3.1; + if (a != 6) return false; + a *= 2.2; + if (a != 13) return false; + if (&(a /= 1.5) != &a) return false; + if (a != 8) return false; return true; } static_assert(test_int(), ""); @@ -374,6 +382,30 @@ namespace compound_assign { } static_assert(test_float(), ""); + constexpr bool test_bool() { + bool b = false; + b |= 2; + if (b != true) return false; + b <<= 1; + if (b != true) return false; + b *= 2; + if (b != true) return false; + b -= 1; + if (b != false) return false; + b -= 1; + if (b != true) return false; + b += -1; + if (b != false) return false; + b += 1; + if (b != true) return false; + b += 1; + if (b != true) return false; + b ^= b; + if (b != false) return false; + return true; + } + static_assert(test_bool(), ""); + constexpr bool test_ptr() { int arr[123] = {}; int *p = arr; @@ -420,7 +452,7 @@ namespace compound_assign { static_assert(test_bounds("foo", 0)[0] == 'f', ""); static_assert(test_bounds("foo", 3)[0] == 0, ""); static_assert(test_bounds("foo", 4)[-3] == 'o', ""); - static_assert(test_bounds("foo" + 4, -4)[0] == 'f', ""); + static_assert(test_bounds(&"foo"[4], -4)[0] == 'f', ""); static_assert(test_bounds("foo", 5) != 0, ""); // expected-error {{constant}} expected-note {{call}} static_assert(test_bounds("foo", -1) != 0, ""); // expected-error {{constant}} expected-note {{call}} static_assert(test_bounds("foo", 1000) != 0, ""); // expected-error {{constant}} expected-note {{call}} @@ -879,7 +911,7 @@ namespace Bitfields { --a.n; --a.u; a.n = -a.n * 3; - return a.b == false && a.n == 3 && a.u == 31; + return a.b == true && a.n == 3 && a.u == 31; } static_assert(test(), ""); } @@ -1098,3 +1130,8 @@ constexpr E e2 = E{0}; static_assert(e2.x != e2.y, ""); } // namespace IndirectFields + +constexpr bool indirect_builtin_constant_p(const char *__s) { + return __builtin_constant_p(*__s); +} +constexpr bool n = indirect_builtin_constant_p("a"); diff --git a/test/SemaCXX/constant-expression-cxx2a.cpp b/test/SemaCXX/constant-expression-cxx2a.cpp index 18c4a726fd008..bb2a4a07dd8f9 100644 --- a/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/test/SemaCXX/constant-expression-cxx2a.cpp @@ -204,3 +204,10 @@ static_assert(complex_test(makeComplex<_Complex int>(0, 0), std::strong_equality::nonequal)); // TODO: defaulted operator <=> } // namespace ThreeWayComparison + +constexpr bool for_range_init() { + int k = 0; + for (int arr[3] = {1, 2, 3}; int n : arr) k += n; + return k == 6; +} +static_assert(for_range_init()); diff --git a/test/SemaCXX/constexpr-string.cpp b/test/SemaCXX/constexpr-string.cpp index 1145a2081cba9..c348c0ff747dd 100644 --- a/test/SemaCXX/constexpr-string.cpp +++ b/test/SemaCXX/constexpr-string.cpp @@ -1,8 +1,11 @@ -// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++1z -fsyntax-only -verify -pedantic -// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++1z -fsyntax-only -verify -pedantic -fno-signed-char -// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -std=c++1z -fsyntax-only -verify -pedantic -fno-wchar -Dwchar_t=__WCHAR_TYPE__ - -# 6 "/usr/include/string.h" 1 3 4 +// 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=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=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 + +# 9 "/usr/include/string.h" 1 3 4 extern "C" { typedef decltype(sizeof(int)) size_t; @@ -18,10 +21,13 @@ extern "C" { extern void *memcpy(void *d, const void *s, size_t n); extern void *memmove(void *d, const void *s, size_t n); } -# 22 "SemaCXX/constexpr-string.cpp" 2 +# 25 "SemaCXX/constexpr-string.cpp" 2 -# 24 "/usr/include/wchar.h" 1 3 4 +# 27 "/usr/include/wchar.h" 1 3 4 extern "C" { +#if NO_PREDEFINED_WCHAR_T + typedef decltype(L'0') wchar_t; +#endif extern size_t wcslen(const wchar_t *p); extern int wcscmp(const wchar_t *s1, const wchar_t *s2); @@ -35,7 +41,7 @@ extern "C" { extern wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n); } -# 39 "SemaCXX/constexpr-string.cpp" 2 +# 45 "SemaCXX/constexpr-string.cpp" 2 namespace Strlen { constexpr int n = __builtin_strlen("hello"); // ok static_assert(n == 5); @@ -95,11 +101,142 @@ namespace StrcmpEtc { static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1); static_assert(__builtin_memcmp("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'}} + + constexpr unsigned char ku00fe00[] = {0x00, 0xfe, 0x00}; + constexpr unsigned char ku00feff[] = {0x00, 0xfe, 0xff}; + constexpr signed char ks00fe00[] = {0, -2, 0}; + constexpr signed char ks00feff[] = {0, -2, -1}; + static_assert(__builtin_memcmp(ku00feff, ks00fe00, 2) == 0); + static_assert(__builtin_memcmp(ku00feff, ks00fe00, 99) == 1); + static_assert(__builtin_memcmp(ku00fe00, ks00feff, 99) == -1); + static_assert(__builtin_memcmp(ks00feff, ku00fe00, 2) == 0); + static_assert(__builtin_memcmp(ks00feff, ku00fe00, 99) == 1); + static_assert(__builtin_memcmp(ks00fe00, ku00feff, 99) == -1); + static_assert(__builtin_memcmp(ks00fe00, ks00feff, 2) == 0); + static_assert(__builtin_memcmp(ks00feff, ks00fe00, 99) == 1); + static_assert(__builtin_memcmp(ks00fe00, ks00feff, 99) == -1); + + 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); + + constexpr long ksl[] = {0, -1}; + constexpr unsigned int kui[] = {0, 0u - 1}; + constexpr unsigned long long kull[] = {0, 0ull - 1}; + constexpr const auto *kuSizeofLong(void) { + if constexpr(sizeof(long) == sizeof(int)) { + return kui; + } else if constexpr(sizeof(long) == sizeof(long long)) { + return kull; + } else { + return nullptr; + } + } + static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) - 1) == 0); + static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + 0) == 0); + static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + 1) == 0); + static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) - 1) == 0); + static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 0) == 0); + static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 1) == 42); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) - 1) == 0); + 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}} + 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}} } +namespace MultibyteElementTests { +inline namespace Util { +#define STR2(X) #X +#define STR(X) STR2(X) +constexpr const char ByteOrderString[] = STR(__BYTE_ORDER__); +#undef STR +#undef STR2 +constexpr bool LittleEndian{*ByteOrderString == '1'}; + +constexpr size_t GoodFoldArraySize = 42, BadFoldArraySize = 43; +struct NotBadFoldResult {}; +template <size_t> struct FoldResult; +template <> struct FoldResult<GoodFoldArraySize> : NotBadFoldResult {}; +template <typename T, size_t N> +FoldResult<N> *foldResultImpl(T (*ptrToConstantSizeArray)[N]); +struct NotFolded : NotBadFoldResult {}; +NotFolded *foldResultImpl(bool anyPtr); +template <auto Value> struct MetaValue; +template <typename Callable, size_t N, auto ExpectedFoldResult> +auto foldResult(const Callable &, MetaValue<N> *, + MetaValue<ExpectedFoldResult> *) { + int (*maybeVLAPtr)[Callable{}(N) == ExpectedFoldResult + ? GoodFoldArraySize + : BadFoldArraySize] = 0; + return foldResultImpl(maybeVLAPtr); +} +template <typename FoldResultKind, typename Callable, typename NWrap, + typename ExpectedWrap> +constexpr bool checkFoldResult(const Callable &c, NWrap *n, ExpectedWrap *e) { + decltype(static_cast<FoldResultKind *>(foldResult(c, n, e))) *chk{}; + return true; +} +template <size_t N> constexpr MetaValue<N> *withN() { return nullptr; } +template <auto Expected> constexpr MetaValue<Expected> *withExpected() { + return nullptr; +} +} // namespace Util +} // namespace MultibyteElementTests + +namespace MultibyteElementTests::Memcmp { +#ifdef __SIZEOF_INT128__ +constexpr __int128 i128_ff_8_00_8 = -(__int128)1 - -1ull; +constexpr __int128 i128_00_16 = 0; +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memcmp(&i128_ff_8_00_8, &i128_00_16, n); + }, + withN<1u>(), withExpected<LittleEndian ? 0 : 1>())); +#endif + +constexpr const signed char ByteOrderStringReduced[] = { + ByteOrderString[0] - '0', ByteOrderString[1] - '0', + ByteOrderString[2] - '0', ByteOrderString[3] - '0', +}; +constexpr signed int i04030201 = 0x04030201; +constexpr unsigned int u04030201 = 0x04030201u; +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memcmp(ByteOrderStringReduced, &i04030201, n); + }, + withN<sizeof(int)>(), withExpected<0>())); +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memcmp(&u04030201, ByteOrderStringReduced, n); + }, + withN<sizeof(int)>(), withExpected<0>())); + +constexpr unsigned int ui0000FEFF = 0x0000feffU; +constexpr unsigned short usFEFF = 0xfeffU; +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memcmp(&ui0000FEFF, &usFEFF, n); + }, + withN<1u>(), withExpected<LittleEndian ? 0 : -1>())); + +constexpr unsigned int ui08038700 = 0x08038700u; +constexpr unsigned int ui08048600 = 0x08048600u; +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memcmp(&ui08038700, &ui08048600, n); + }, + withN<sizeof(int)>(), withExpected<LittleEndian ? 1 : -1>())); +} + namespace WcscmpEtc { constexpr wchar_t kFoobar[6] = {L'f',L'o',L'o',L'b',L'a',L'r'}; constexpr wchar_t kFoobazfoobar[12] = {L'f',L'o',L'o',L'b',L'a',L'z',L'f',L'o',L'o',L'b',L'a',L'r'}; @@ -187,6 +324,27 @@ namespace StrchrEtc { static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr); // FIXME: Should we reject this? + extern struct Incomplete incomplete; + static_assert(__builtin_memchr(&incomplete, 0, 0u) == nullptr); + static_assert(__builtin_memchr(&incomplete, 0, 1u) == nullptr); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}} + + const unsigned char &u1 = 0xf0; + auto &&i1 = (const signed char []){-128}; // expected-warning {{compound literals are a C99-specific feature}} + static_assert(__builtin_memchr(&u1, -(0x0f + 1), 1) == &u1); + static_assert(__builtin_memchr(i1, 0x80, 1) == i1); + + enum class E : unsigned char {}; + struct EPair { E e, f; }; + constexpr EPair ee{E{240}}; + static_assert(__builtin_memchr(&ee.e, 240, 1) == &ee.e); + + constexpr bool kBool[] = {false, true, false}; + constexpr const bool *const kBoolPastTheEndPtr = kBool + 3; + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, 1, 99) == kBool + 1); + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBool + 1, 0, 99) == kBoolPastTheEndPtr - 1); + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, -1, 3) == nullptr); + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr, 0, 1) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_char_memchr(kStr, 'a', 0) == nullptr); static_assert(__builtin_char_memchr(kStr, 'a', 1) == kStr); static_assert(__builtin_char_memchr(kStr, '\0', 5) == nullptr); @@ -212,6 +370,22 @@ namespace StrchrEtc { constexpr bool b = !memchr("hello", 'h', 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memchr' cannot be used in a constant expression}} } +namespace MultibyteElementTests::Memchr { +constexpr unsigned int u04030201 = 0x04030201; +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memchr(&u04030201, *ByteOrderString - '0', n); + }, + withN<1u>(), withExpected<&u04030201>())); + +constexpr unsigned int uED = 0xEDU; +static_assert(checkFoldResult<NotBadFoldResult>( + [](size_t n) constexpr { + return __builtin_memchr(&uED, 0xED, n); + }, + withN<1u>(), withExpected<LittleEndian ? &uED : nullptr>())); +} + namespace WcschrEtc { constexpr const wchar_t *kStr = L"abca\xffff\0dL"; constexpr wchar_t kFoo[] = {L'f', L'o', L'o'}; @@ -269,15 +443,15 @@ namespace MemcpyEtc { wchar_t arr[4] = {1, 2, 3, 4}; __builtin_wmemcpy(arr + a, arr + b, n); // expected-note@-1 2{{overlapping memory regions}} - // expected-note-re@-2 {{source is not a contiguous array of at least 2 elements of type '{{wchar_t|int}}'}} - // expected-note-re@-3 {{destination is not a contiguous array of at least 3 elements of type '{{wchar_t|int}}'}} + // expected-note@-2 {{source is not a contiguous array of at least 2 elements of type 'wchar_t'}} + // expected-note@-3 {{destination is not a contiguous array of at least 3 elements of type 'wchar_t'}} return result(arr); } constexpr int test_wmemmove(int a, int b, int n) { wchar_t arr[4] = {1, 2, 3, 4}; __builtin_wmemmove(arr + a, arr + b, n); - // expected-note-re@-1 {{source is not a contiguous array of at least 2 elements of type '{{wchar_t|int}}'}} - // expected-note-re@-2 {{destination is not a contiguous array of at least 3 elements of type '{{wchar_t|int}}'}} + // expected-note@-1 {{source is not a contiguous array of at least 2 elements of type 'wchar_t'}} + // expected-note@-2 {{destination is not a contiguous array of at least 3 elements of type 'wchar_t'}} return result(arr); } @@ -317,6 +491,23 @@ namespace MemcpyEtc { static_assert(test_wmemmove(0, 3, 2) == 4234); // expected-error {{constant}} expected-note {{in call}} static_assert(test_wmemmove(2, 0, 3) == 4234); // expected-error {{constant}} expected-note {{in call}} +#define fold(x) (__builtin_constant_p(0) ? (x) : (x)) + + wchar_t global; + constexpr wchar_t *null = 0; + static_assert(__builtin_memcpy(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memcpy' is nullptr}} + static_assert(__builtin_memmove(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memmove' is nullptr}} + static_assert(__builtin_wmemcpy(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'wmemcpy' is nullptr}} + static_assert(__builtin_wmemmove(&global, null, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'wmemmove' is nullptr}} + static_assert(__builtin_memcpy(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'memcpy' is nullptr}} + static_assert(__builtin_memmove(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'memmove' is nullptr}} + static_assert(__builtin_wmemcpy(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'wmemcpy' is nullptr}} + static_assert(__builtin_wmemmove(null, &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'wmemmove' is nullptr}} + static_assert(__builtin_memcpy(&global, fold((wchar_t*)123), sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memcpy' is (void *)123}} + static_assert(__builtin_memcpy(fold(reinterpret_cast<wchar_t*>(123)), &global, sizeof(wchar_t))); // expected-error {{}} expected-note {{destination of 'memcpy' is (void *)123}} + constexpr struct Incomplete *null_incomplete = 0; + static_assert(__builtin_memcpy(null_incomplete, null_incomplete, sizeof(wchar_t))); // expected-error {{}} expected-note {{source of 'memcpy' is nullptr}} + // Copying is permitted for any trivially-copyable type. struct Trivial { char k; short s; constexpr bool ok() { return k == 3 && s == 4; } }; constexpr bool test_trivial() { @@ -370,4 +561,41 @@ namespace MemcpyEtc { // designators until we have a long enough matching size, if both designators // point to the start of their respective final elements. static_assert(test_derived_to_base(2) == 3434); // expected-error {{constant}} expected-note {{in call}} + + // Check that when address-of an array is passed to a tested function the + // array can be fully copied. + constexpr int test_address_of_const_array_type() { + int arr[4] = {1, 2, 3, 4}; + __builtin_memmove(&arr, &arr, sizeof(arr)); + return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3]; + } + static_assert(test_address_of_const_array_type() == 1234); + + // Check that an incomplete array is rejected. + constexpr int test_incomplete_array_type() { // expected-error {{never produces a constant}} + extern int arr[]; + __builtin_memmove(arr, arr, 4 * sizeof(arr[0])); + // expected-note@-1 2{{'memmove' not supported: source is not a contiguous array of at least 4 elements of type 'int'}} + return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3]; + } + static_assert(test_incomplete_array_type() == 1234); // expected-error {{constant}} expected-note {{in call}} + + // Check that a pointer to an incomplete array is rejected. + constexpr int test_address_of_incomplete_array_type() { // expected-error {{never produces a constant}} + extern int arr[]; + __builtin_memmove(&arr, &arr, 4 * sizeof(arr[0])); + // expected-note@-1 2{{cannot constant evaluate 'memmove' between objects of incomplete type 'int []'}} + return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3]; + } + static_assert(test_address_of_incomplete_array_type() == 1234); // expected-error {{constant}} expected-note {{in call}} + + // Check that a pointer to an incomplete struct is rejected. + constexpr bool test_address_of_incomplete_struct_type() { // expected-error {{never produces a constant}} + struct Incomplete; + extern Incomplete x, y; + __builtin_memcpy(&x, &x, 4); + // expected-note@-1 2{{cannot constant evaluate 'memcpy' between objects of incomplete type 'Incomplete'}} + return true; + } + static_assert(test_address_of_incomplete_struct_type()); // expected-error {{constant}} expected-note {{in call}} } diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp index 105605c6e37b4..33ea496634919 100644 --- a/test/SemaCXX/constructor.cpp +++ b/test/SemaCXX/constructor.cpp @@ -86,3 +86,14 @@ A::S::operator int() { return 1; } A::S::~S() {} +namespace PR38286 { + // FIXME: It'd be nice to give more consistent diagnostics for these cases + // (but they're all failing for somewhat different reasons...). + template<typename> struct A; + template<typename T> A<T>::A() {} // expected-error {{incomplete type 'A' named in nested name specifier}} + /*FIXME: needed to recover properly from previous error*/; + template<typename> struct B; + template<typename T> void B<T>::f() {} // expected-error {{out-of-line definition of 'f' from class 'B<type-parameter-0-0>'}} + template<typename> struct C; + template<typename T> C<T>::~C() {} // expected-error {{no type named 'C' in 'C<type-parameter-0-0>'}} +} diff --git a/test/SemaCXX/coreturn-eh.cpp b/test/SemaCXX/coreturn-eh.cpp new file mode 100644 index 0000000000000..79065736c0a41 --- /dev/null +++ b/test/SemaCXX/coreturn-eh.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fcxx-exceptions -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wall -Wextra -Wno-error=unreachable-code +// expected-no-diagnostics + +#include "Inputs/std-coroutine.h" + +using std::experimental::suspend_always; +using std::experimental::suspend_never; + +struct awaitable { + bool await_ready(); + void await_suspend(std::experimental::coroutine_handle<>); // FIXME: coroutine_handle + void await_resume(); +} a; + +struct object { ~object() {} }; + +struct promise_void_return_value { + void get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); + void return_value(object); +}; + +struct VoidTagReturnValue { + struct promise_type { + VoidTagReturnValue get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); + void return_value(object); + }; +}; + +template <typename T1> +struct std::experimental::coroutine_traits<void, T1> { using promise_type = promise_void_return_value; }; + +VoidTagReturnValue test() { + object x = {}; + try { + co_return {}; + } catch (...) { + throw; + } +} diff --git a/test/SemaCXX/coroutine-rvo.cpp b/test/SemaCXX/coroutine-rvo.cpp new file mode 100644 index 0000000000000..8521b8506fd04 --- /dev/null +++ b/test/SemaCXX/coroutine-rvo.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -stdlib=libc++ -std=c++1z -fcoroutines-ts -fsyntax-only + +namespace std::experimental { +template <class Promise = void> struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; + +template <> struct coroutine_handle<void> { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template <class PromiseType> + coroutine_handle(coroutine_handle<PromiseType>) noexcept; +}; + +template <class... Args> +struct void_t_imp { + using type = void; +}; +template <class... Args> +using void_t = typename void_t_imp<Args...>::type; + +template <class T, class = void> +struct traits_sfinae_base {}; + +template <class T> +struct traits_sfinae_base<T, void_t<typename T::promise_type>> { + using promise_type = typename T::promise_type; +}; + +template <class Ret, class... Args> +struct coroutine_traits : public traits_sfinae_base<Ret> {}; +} + +struct suspend_never { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct MoveOnly { + MoveOnly() {}; + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept {}; + ~MoveOnly() {}; +}; + +template <typename T> +struct task { + struct promise_type { + auto initial_suspend() { return suspend_never{}; } + auto final_suspend() { return suspend_never{}; } + auto get_return_object() { return task{}; } + static void unhandled_exception() {} + void return_value(T&& value) {} + }; +}; + +task<MoveOnly> f() { + MoveOnly value; + co_return value; +} + +int main() { + f(); + return 0; +} + +// expected-no-diagnostics diff --git a/test/SemaCXX/coroutine-source-location-crash.cpp b/test/SemaCXX/coroutine-source-location-crash.cpp deleted file mode 100644 index 04fb1d45c524d..0000000000000 --- a/test/SemaCXX/coroutine-source-location-crash.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \ -// RUN: -fsyntax-only -ast-dump | FileCheck %s -#include "Inputs/std-coroutine.h" - -using namespace std::experimental; - -struct A { - bool await_ready(); - void await_resume(); - template <typename F> - void await_suspend(F); -}; - -struct coro_t { - struct promise_type { - coro_t get_return_object(); - suspend_never initial_suspend(); - suspend_never final_suspend(); - void return_void(); - static void unhandled_exception(); - }; -}; - -// {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36> -// CHECK-LABEL: FunctionDecl {{.*}} f 'coro_t (int)' -coro_t f(int n) { - A a{}; - // CHECK: CoawaitExpr {{0x[0-9a-fA-F]+}} <col:3, col:12> - // CHECK-NEXT: DeclRefExpr {{0x[0-9a-fA-F]+}} <col:12> - // CHECK-NEXT: CXXMemberCallExpr {{0x[0-9a-fA-F]+}} <col:12> - // CHECK-NEXT: MemberExpr {{0x[0-9a-fA-F]+}} <col:12> - co_await a; -} diff --git a/test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp b/test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp new file mode 100644 index 0000000000000..7237fbf9db7f0 --- /dev/null +++ b/test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++03 -triple x86_64-pc-linux-gnu %s \ +// RUN: -faligned-allocation -emit-llvm -o - -Wno-c++11-extensions | FileCheck %s + +// Ensure Clang doesn't confuse std::align_val_t with the sized deallocation +// parameter when the enum type is unscoped. Libc++ does this in C++03 in order +// to support aligned allocation in that dialect. + +using size_t = __decltype(sizeof(0)); + +namespace std { +enum align_val_t : size_t {}; +} +_Static_assert(__is_same(__underlying_type(std::align_val_t), size_t), ""); + +// CHECK-LABEL: define void @_Z1fPi( +void f(int *p) { + // CHECK-NOT: call void @_ZdlPvSt11align_val_t( + // CHECK: call void @_ZdlPv( + // CHECK: ret void + delete p; +} diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index f623dc765f88c..6346e1c235384 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -99,8 +99,6 @@ namespace DefaultedFnExceptionSpec { Error<char> c; // expected-note 2{{instantiation of}} struct DelayImplicit { - // FIXME: The location of this note is terrible. The instantiation was - // triggered by the uses of the functions in the decltype expressions below. Error<int> e; // expected-note 6{{instantiation of}} }; Error<float> *e; @@ -109,9 +107,9 @@ namespace DefaultedFnExceptionSpec { // a defaulted special member function that calls the function is needed. // Use in an unevaluated operand still results in the exception spec being // needed. - void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit()))); - void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>())); - void test3(decltype(DelayImplicit(declval<const DelayImplicit>()))); + void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit()))); // expected-note 4{{in evaluation of exception specification}} + void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>())); // expected-note {{in evaluation of exception specification}} + void test3(decltype(DelayImplicit(declval<const DelayImplicit>()))); // expected-note {{in evaluation of exception specification}} // Any odr-use needs the exception specification. void f(Error<double> *p) { diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index b9af67948bfc9..80efd810f0984 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -59,7 +59,7 @@ struct good_const { good_const gc; struct no_default { - no_default() = delete; // expected-note 4{{deleted here}} + no_default() = delete; // expected-note 5{{deleted here}} }; struct no_dtor { ~no_dtor() = delete; // expected-note 2{{deleted here}} @@ -108,8 +108,8 @@ struct has_friend { has_friend hf; struct defaulted_delete { - no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}} - defaulted_delete() = default; // expected-note{{implicitly deleted here}} + no_default nd; // expected-note 2{{because field 'nd' has a deleted default constructor}} + defaulted_delete() = default; // expected-note{{implicitly deleted here}} expected-warning {{implicitly deleted}} }; defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}} diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp index 90b11f3a9e230..a13aa238de663 100644 --- a/test/SemaCXX/cxx0x-initializer-scalars.cpp +++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -127,3 +127,26 @@ namespace PR12118 { static_assert(sizeof(f({0})) == sizeof(one), "bad overload"); } } + +namespace excess_braces_sfinae { + using valid = int&; + using invalid = float&; + + template<typename T> valid braces1(decltype(T{0})*); + template<typename T> invalid braces1(...); + + template<typename T> valid braces2(decltype(T{{0}})*); + template<typename T> invalid braces2(...); + + template<typename T> valid braces3(decltype(T{{{0}}})*); + template<typename T> invalid braces3(...); + + valid a = braces1<int>(0); + invalid b = braces2<int>(0); + invalid c = braces3<int>(0); + + struct X { int n; }; + valid d = braces1<X>(0); + valid e = braces2<X>(0); + invalid f = braces3<X>(0); +} diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx11-compat.cpp index b9ccadd85c2d7..07cd6b1fcf93b 100644 --- a/test/SemaCXX/cxx0x-compat.cpp +++ b/test/SemaCXX/cxx11-compat.cpp @@ -47,12 +47,30 @@ template<int ...N> int f() { // expected-warning {{C++11 extension}} #else +decltype(auto) x = 0; // expected-warning {{'decltype(auto)' type specifier is incompatible}} + auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++14}} -static_assert(true); // expected-warning {{incompatible with C++ standards before C++17}} -template<int ...N> int f() { return (N + ...); } // expected-warning {{incompatible with C++ standards before C++17}} +auto generic_lambda = + []( + auto // expected-warning {{generic lambdas are incompatible}} + *a) {}; + +auto deduced_return_type(); // expected-warning {{incompatible with C++ standards before C++14}} +auto *another_deduced_return_type(); // expected-warning {{incompatible with C++ standards before C++14}} +decltype(auto) also_deduced_return_type(); // expected-warning {{return type deduction}} expected-warning {{'decltype(auto)' type specifier is incompatible}} +int f(); +auto (*not_deduced_return_type)() = f; + +auto deduced_lambda_return_type = []() -> + auto // expected-warning {{return type deduction is incompatible}} +{}; + +auto trailing_non_deduced_return_type() -> int; +auto trailing_deduced_return_type() -> auto; // expected-warning {{incompatible with C++ standards before C++14}} -namespace [[]] NS_with_attr {} // expected-warning {{incompatible with C++ standards before C++17}} -enum { e [[]] }; // expected-warning {{incompatible with C++ standards before C++17}} +struct A { + operator auto(); // expected-warning {{return type deduction is incompatible}} +}; #endif diff --git a/test/SemaCXX/cxx14-compat.cpp b/test/SemaCXX/cxx14-compat.cpp new file mode 100644 index 0000000000000..d70f477cd09ac --- /dev/null +++ b/test/SemaCXX/cxx14-compat.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++14-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++14-compat-pedantic -verify %s + +#if __cplusplus < 201402L + +// expected-no-diagnostics +// FIXME: C++11 features removed or changed in C++14? + +#else + +static_assert(true); // expected-warning {{incompatible with C++ standards before C++17}} + +template<int ...N> int f() { return (N + ...); } // expected-warning {{incompatible with C++ standards before C++17}} + +namespace [[]] NS_with_attr {} // expected-warning {{incompatible with C++ standards before C++17}} +enum { e [[]] }; // expected-warning {{incompatible with C++ standards before C++17}} + +template<typename T = int> struct X {}; +X x; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17; for compatibility, use explicit type name 'X<int>'}} + +template<template<typename> class> struct Y {}; +Y<X> yx; // ok, not class template argument deduction + +template<typename T> void f(T t) { + X x = t; // expected-warning {{incompatible}} +} + +template<typename T> void g(T t) { + typename T::X x = t; // expected-warning {{incompatible}} +} +struct A { template<typename T> struct X { X(T); }; }; +void h(A a) { g(a); } // expected-note {{in instantiation of}} + +#endif diff --git a/test/SemaCXX/cxx17-compat.cpp b/test/SemaCXX/cxx17-compat.cpp index 3b814340c6daf..eee9c239d188d 100644 --- a/test/SemaCXX/cxx17-compat.cpp +++ b/test/SemaCXX/cxx17-compat.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++17 -pedantic -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++2a -Wc++17-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++2a -Wc++17-compat-pedantic -verify %s -Wno-defaulted-function-deleted struct A {}; int (A::*pa)() const&; @@ -27,3 +27,39 @@ struct B { // expected-warning@-4 {{default member initializer for bit-field is incompatible with C++ standards before C++2a}} #endif }; + +auto Lambda = []{}; +decltype(Lambda) AnotherLambda; +#if __cplusplus <= 201703L + // expected-error@-2 {{no matching constructor}} expected-note@-3 2{{candidate}} +#else + // expected-warning@-4 {{default construction of lambda is incompatible with C++ standards before C++2a}} +#endif + +void copy_lambda() { Lambda = Lambda; } +#if __cplusplus <= 201703L + // expected-error@-2 {{deleted}} expected-note@-10 {{lambda}} +#else + // expected-warning@-4 {{assignment of lambda is incompatible with C++ standards before C++2a}} +#endif + +struct DefaultDeleteWrongTypeBase { + DefaultDeleteWrongTypeBase(DefaultDeleteWrongTypeBase&); +}; +struct DefaultDeleteWrongType : DefaultDeleteWrongTypeBase { + DefaultDeleteWrongType(const DefaultDeleteWrongType&) = default; +#if __cplusplus <= 201703L + // expected-error@-2 {{a member or base requires it to be non-const}} +#else + // expected-warning@-4 {{explicitly defaulting this copy constructor with a type different from the implicit type is incompatible with C++ standards before C++2a}} +#endif +}; + +void ForRangeInit() { + for (int arr[3] = {1, 2, 3}; int n : arr) {} +#if __cplusplus <= 201703L + // expected-warning@-2 {{range-based for loop initialization statements are a C++2a extension}} +#else + // expected-warning@-4 {{range-based for loop initialization statements are incompatible with C++ standards before C++2a}} +#endif +} diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index 13ff751acae4d..fafc6ead73c41 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -552,3 +552,71 @@ namespace PR24989 { void forinit_decltypeauto() { for (decltype(auto) forinit_decltypeauto_inner();;) {} // expected-warning {{interpreted as a function}} expected-note {{replace}} } + +namespace PR33222 { + auto f1(); + auto f2(); + + template<typename T> decltype(auto) g0(T x) { return x.n; } + template<typename T> decltype(auto) g1(T); + template<typename T> decltype(auto) g2(T); + + struct X { + static auto f1(); + static auto f2(); + + template<typename T> static decltype(auto) g0(T x) { return x.n; } + template<typename T> static decltype(auto) g1(T); + template<typename T> static decltype(auto) g2(T); + }; + + template<typename U> class A { + friend auto f1(); + friend auto f2(); + + friend decltype(auto) g0<>(A); + template<typename T> friend decltype(auto) g1(T); + template<typename T> friend decltype(auto) g2(T); + + friend auto X::f1(); + friend auto X::f2(); + + // FIXME (PR38882): 'A' names the class template not the injected-class-name here! + friend decltype(auto) X::g0<>(A<U>); + // FIXME (PR38882): ::T hides the template parameter if both are named T here! + template<typename T_> friend decltype(auto) X::g1(T_); + template<typename T_> friend decltype(auto) X::g2(T_); + + int n; + }; + + auto f1() { return A<int>().n; } + template<typename T> decltype(auto) g1(T x) { return A<int>().n; } + + auto X::f1() { return A<int>().n; } + template<typename T> decltype(auto) X::g1(T x) { return A<int>().n; } + + A<int> ai; + int k1 = g0(ai); + int k2 = X::g0(ai); + + int k3 = g1(ai); + int k4 = X::g1(ai); + + auto f2() { return A<int>().n; } + template<typename T> decltype(auto) g2(T x) { return A<int>().n; } + + auto X::f2() { return A<int>().n; } + template<typename T> decltype(auto) X::g2(T x) { return A<int>().n; } + + int k5 = g2(ai); + int k6 = X::g2(ai); + + template<typename> struct B { + auto *q() { return (float*)0; } // expected-note 2{{previous}} + }; + template<> auto *B<char[1]>::q() { return (int*)0; } + template<> auto B<char[2]>::q() { return (int*)0; } // expected-error {{return type}} + // FIXME: suppress this follow-on error: expected-error@-1 {{cannot initialize}} + template<> int B<char[3]>::q() { return 0; } // expected-error {{return type}} +} diff --git a/test/SemaCXX/cxx1y-init-captures.cpp b/test/SemaCXX/cxx1y-init-captures.cpp index 4b82452ed5924..16cffb2a914bc 100644 --- a/test/SemaCXX/cxx1y-init-captures.cpp +++ b/test/SemaCXX/cxx1y-init-captures.cpp @@ -144,13 +144,13 @@ int test(T t = T{}) { }; } { // will need to capture x in outer lambda - const int x = 10; //expected-note 2{{declared}} - auto L = [z = x](char a) { //expected-note 2{{begins}} - auto M = [&y = x](T b) { //expected-error 2{{cannot be implicitly captured}} + const int x = 10; //expected-note {{declared}} + auto L = [z = x](char a) { //expected-note {{begins}} + auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}} return y; }; return M; - }; + }; } { // no captures diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index cbf7c2eee51cd..c310c651408d6 100644 --- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -307,6 +307,13 @@ namespace dependent { template int Var(int); template int Cast(int); template int New(int); + + template<template<typename> typename Y> void test() { + Y(0); + new Y(0); + Y y(0); + } + template void test<X>(); } namespace injected_class_name { diff --git a/test/SemaCXX/cxx1z-init-statement.cpp b/test/SemaCXX/cxx1z-init-statement.cpp index d37acd08ce77d..eea2589ab7c62 100644 --- a/test/SemaCXX/cxx1z-init-statement.cpp +++ b/test/SemaCXX/cxx1z-init-statement.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++1z -verify %s -// RUN: %clang_cc1 -std=c++17 -verify %s +// RUN: %clang_cc1 -std=c++1z -Wno-unused-value -verify %s +// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify %s void testIf() { int x = 0; @@ -12,7 +12,7 @@ void testIf() { int x = 0; // expected-error {{redefinition of 'x'}} if (x; int a = 0) ++a; - if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}} + if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} int a = 0; // expected-error {{redefinition of 'a'}} else int a = 0; // expected-error {{redefinition of 'a'}} @@ -48,7 +48,7 @@ void testSwitch() { ++a; } - switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}} + switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} case 0: int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}} case 1: diff --git a/test/SemaCXX/cxx2a-compat.cpp b/test/SemaCXX/cxx2a-compat.cpp new file mode 100644 index 0000000000000..d51f1e6aab130 --- /dev/null +++ b/test/SemaCXX/cxx2a-compat.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++2a-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++2a -pedantic -verify %s + +struct A { // expected-note 0+{{candidate}} + A() = default; // expected-note 0+{{candidate}} + int x, y; +}; +A a1 = {1, 2}; +#if __cplusplus <= 201703L + // expected-warning@-2 {{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}} +#else + // expected-error@-4 {{no matching constructor}} +#endif +A a2 = {}; + +struct B : A { A a; }; +B b1 = {{}, {}}; // ok +B b2 = {1, 2, 3, 4}; +#if __cplusplus <= 201703L + // expected-warning@-2 2{{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}} +#else + // expected-error@-4 2{{no viable conversion from 'int' to 'A'}} +#endif + +// Essentially any use of a u8 string literal in C++<=17 is broken by C++20. +// Just warn on all such string literals. +struct string { string(const char*); }; // expected-note 0+{{candidate}} +char u8arr[] = u8"hello"; +const char *u8ptr = "wo" u8"rld"; +string u8str = u8"test" u8"test"; +#if __cplusplus <= 201703L +// expected-warning@-4 {{type of UTF-8 string literal will change}} expected-note@-4 {{remove 'u8' prefix}} +// expected-warning@-4 {{type of UTF-8 string literal will change}} expected-note@-4 {{remove 'u8' prefix}} +// expected-warning@-4 {{type of UTF-8 string literal will change}} expected-note@-4 {{remove 'u8' prefix}} +#else +// expected-error@-8 {{ISO C++20 does not permit initialization of char array with UTF-8 string literal}} +// expected-error@-8 {{cannot initialize a variable of type 'const char *' with an lvalue of type 'const char8_t [6]'}} +// expected-error@-8 {{no viable conversion from 'const char8_t [9]' to 'string'}} +#endif diff --git a/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/test/SemaCXX/cxx2a-initializer-aggregates.cpp new file mode 100644 index 0000000000000..9c438d399b348 --- /dev/null +++ b/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++2a %s -verify + +namespace class_with_ctor { + struct A { // expected-note 6{{candidate}} + A() = default; // expected-note 3{{candidate}} + int x; + int y; + }; + A a = {1, 2}; // expected-error {{no matching constructor}} + + struct B { + int x; + int y; + }; + B b1 = B(); // trigger declaration of implicit ctors + B b2 = {1, 2}; // ok + + struct C : A { + A a; + }; + C c1 = {{}, {}}; // ok, call default ctor twice + C c2 = {{1, 2}, {3, 4}}; // expected-error 2{{no matching constructor}} +} diff --git a/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp b/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp new file mode 100644 index 0000000000000..e555f16ecc1ec --- /dev/null +++ b/test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +auto a = []{}; +decltype(a) a2; +void f(decltype(a) x, decltype(a) y) { + x = y; + x = static_cast<decltype(a)&&>(y); +} + +template<typename T> +struct X { + constexpr X() { T::error; } // expected-error {{'::'}} + X(const X&); + constexpr X &operator=(const X&) { T::error; } // expected-error {{'::'}} + constexpr X &operator=(X&&) { T::error; } // expected-error {{'::'}} +}; +extern X<int> x; +auto b = [x = x]{}; // expected-note 3{{in instantiation of}} +decltype(b) b2; // expected-note {{in implicit default constructor}} +void f(decltype(b) x, decltype(b) y) { + x = y; // expected-note {{in implicit copy assignment}} + x = static_cast<decltype(b)&&>(y); // expected-note {{in implicit move assignment}} +} + +struct Y { + Y() = delete; // expected-note {{deleted}} + Y(const Y&); + Y &operator=(const Y&) = delete; // expected-note 2{{deleted}} + Y &operator=(Y&&) = delete; +}; +extern Y y; +auto c = [y = y]{}; // expected-note 3{{deleted because}} +decltype(c) c2; // expected-error {{deleted}} +void f(decltype(c) x, decltype(c) y) { + x = y; // expected-error {{deleted}} + x = static_cast<decltype(c)&&>(y); // expected-error {{deleted}} +} diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index f814a06f13be0..885ab110ab1fa 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -103,7 +103,8 @@ struct RefQualifier { auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}} #ifdef CXX14COMPAT -auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}} +auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}} +// expected-warning@-1 {{return type deduction is incompatible with C++ standards before C++14}} #endif void RangeFor() { diff --git a/test/SemaCXX/delete-non-virtual-dtor.cpp b/test/SemaCXX/delete-non-virtual-dtor.cpp new file mode 100644 index 0000000000000..b64eca3527f3e --- /dev/null +++ b/test/SemaCXX/delete-non-virtual-dtor.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -verify -DDIAG1 +// RUN: %clang_cc1 %s -verify -DDIAG1 -DDIAG2 -Wdelete-non-virtual-dtor +// RUN: %clang_cc1 %s -verify -DDIAG1 -Wmost -Wno-delete-non-abstract-non-virtual-dtor +// RUN: %clang_cc1 %s -verify -DDIAG2 -Wmost -Wno-delete-abstract-non-virtual-dtor +// RUN: %clang_cc1 %s -verify -Wmost -Wno-delete-non-virtual-dtor + +#ifndef DIAG1 +#ifndef DIAG2 +// expected-no-diagnostics +#endif +#endif + +struct S1 { + ~S1() {} + virtual void abs() = 0; +}; + +void f1(S1 *s1) { delete s1; } +#ifdef DIAG1 +// expected-warning@-2 {{delete called on 'S1' that is abstract but has non-virtual destructor}} +#endif + +struct S2 { + ~S2() {} + virtual void real() {} +}; +void f2(S2 *s2) { delete s2; } +#ifdef DIAG2 +// expected-warning@-2 {{delete called on non-final 'S2' that has virtual functions but non-virtual destructor}} +#endif diff --git a/test/SemaCXX/designated-initializers.cpp b/test/SemaCXX/designated-initializers.cpp index e5b5f3c9cce2e..04002c0b6c11f 100644 --- a/test/SemaCXX/designated-initializers.cpp +++ b/test/SemaCXX/designated-initializers.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Winitializer-overrides %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Woverride-init %s template <typename T> struct Foo { struct SubFoo { diff --git a/test/SemaCXX/dr1301.cpp b/test/SemaCXX/dr1301.cpp index ec0db74554a87..b7dc91d563300 100644 --- a/test/SemaCXX/dr1301.cpp +++ b/test/SemaCXX/dr1301.cpp @@ -6,7 +6,7 @@ struct A { // expected-note 2{{candidate}} int a = A().n; // expected-error {{no matching constructor}} struct B { - B() = delete; // expected-note 3{{here}} + B() = delete; // expected-note 4{{here}} int n; }; int b = B().n; // expected-error {{call to deleted}} @@ -17,8 +17,8 @@ struct C { int c = C().b.n; // expected-error {{call to implicitly-deleted default}} struct D { - D() = default; // expected-note {{here}} - B b; // expected-note {{'b' has a deleted default constructor}} + D() = default; // expected-note {{here}} expected-warning {{implicitly deleted}} + B b; // expected-note 2{{'b' has a deleted default constructor}} }; int d = D().b.n; // expected-error {{call to implicitly-deleted default}} diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp index 93014f50d5080..ba520b047a324 100644 --- a/test/SemaCXX/enable_if.cpp +++ b/test/SemaCXX/enable_if.cpp @@ -414,7 +414,8 @@ static_assert(templated<1>() == 1, ""); template <int N> constexpr int callTemplated() { return templated<N>(); } -constexpr int B = callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-2{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-9{{candidate disabled}} +constexpr int B = 10 + // the carat for the error should be pointing to the problematic call (on the next line), not here. + callTemplated<0>(); // expected-error{{initialized by a constant expression}} expected-error@-3{{no matching function for call to 'templated'}} expected-note{{in instantiation of function template}} expected-note@-10{{candidate disabled}} static_assert(callTemplated<1>() == 1, ""); } diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp index cfe5760112f6d..16ebebe31b6db 100644 --- a/test/SemaCXX/enum.cpp +++ b/test/SemaCXX/enum.cpp @@ -109,6 +109,8 @@ enum { overflow = 123456 * 234567 }; #if __cplusplus >= 201103L // expected-warning@-2 {{not an integral constant expression}} // expected-note@-3 {{value 28958703552 is outside the range of representable values}} +#else +// expected-warning@-5 {{overflow in expression; result is -1106067520 with type 'int'}} #endif // PR28903 diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp index f301a63503dd4..6ad19aab397bd 100644 --- a/test/SemaCXX/exception-spec.cpp +++ b/test/SemaCXX/exception-spec.cpp @@ -5,3 +5,50 @@ namespace MissingOnTemplate { template<typename T> void foo(T); // expected-error {{missing exception specification 'noexcept(true)'}} void test() { foo(0); } } + +struct UseBeforeComplete1 { + ~UseBeforeComplete1(); // expected-note {{previous}} + struct X { + friend UseBeforeComplete1::~UseBeforeComplete1() noexcept; // expected-warning {{previously declared with an implicit}} + }; +}; + +struct ThrowingDtor { ~ThrowingDtor() noexcept(false); }; +struct UseBeforeComplete2 { + ~UseBeforeComplete2(); // expected-note {{previous}} + struct X { + friend UseBeforeComplete2::~UseBeforeComplete2() noexcept; // expected-error {{does not match previous}} + }; + ThrowingDtor td; +}; + +struct UseBeforeComplete3 { + ~UseBeforeComplete3(); + struct X { + friend UseBeforeComplete3::~UseBeforeComplete3(); // ok, implicitly noexcept(true) + }; +}; +static_assert(noexcept(UseBeforeComplete3()), ""); + +struct UseBeforeComplete4 { + ~UseBeforeComplete4(); + struct X { + friend UseBeforeComplete4::~UseBeforeComplete4(); // ok, implicitly noexcept(false) + }; + ThrowingDtor td; +}; +static_assert(!noexcept(UseBeforeComplete4()), ""); + +namespace AssignmentOp { + struct D1; + struct D2; + struct B { + B &operator=(const B&); + virtual D1 &operator=(const D1&) noexcept; // expected-note {{overridden}} + virtual D2 &operator=(const D2&) noexcept; // expected-note {{overridden}} + }; + struct D1 : B {}; // expected-error {{more lax}} + struct D2 : B { + D2 &operator=(const D2&); // expected-error {{more lax}} + }; +} diff --git a/test/SemaCXX/for-range-dereference.cpp b/test/SemaCXX/for-range-dereference.cpp index 7377199024e51..de4958c31bce7 100644 --- a/test/SemaCXX/for-range-dereference.cpp +++ b/test/SemaCXX/for-range-dereference.cpp @@ -17,7 +17,7 @@ struct DeletedEnd : public T { struct DeletedADLBegin { }; int* begin(DeletedADLBegin) = delete; //expected-note {{candidate function has been explicitly deleted}} \ - expected-note 5 {{candidate function not viable: no known conversion}} + expected-note 6 {{candidate function not viable: no known conversion}} struct PrivateEnd { Data *begin(); @@ -27,7 +27,7 @@ struct PrivateEnd { }; struct ADLNoEnd { }; -Data * begin(ADLNoEnd); // expected-note 6 {{candidate function not viable: no known conversion}} +Data * begin(ADLNoEnd); // expected-note 7 {{candidate function not viable: no known conversion}} struct OverloadedStar { T operator*(); @@ -45,7 +45,7 @@ void f() { for (auto i : parr) { }// expected-error{{invalid range expression of type 'int (*)[10]'; did you mean to dereference it with '*'?}} NoBegin NB; - for (auto i : NB) { }// expected-error{{range type 'NoBegin' has 'end' member but no 'begin' member}} + for (auto i : NB) { }// expected-error{{invalid range expression of type 'NoBegin'; no viable 'begin' function available}} NoBegin *pNB; for (auto i : pNB) { }// expected-error{{invalid range expression of type 'NoBegin *'; no viable 'begin' function available}} NoBegin **ppNB; diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index 477789b56c142..5424b7a8ee797 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -244,7 +244,7 @@ void foo () { int b = 1, a[b]; a[0] = 0; - [&] { for (int c : a) 0; } (); + [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}} } diff --git a/test/SemaCXX/friend-template-redecl.cpp b/test/SemaCXX/friend-template-redecl.cpp new file mode 100644 index 0000000000000..3e05964fb2882 --- /dev/null +++ b/test/SemaCXX/friend-template-redecl.cpp @@ -0,0 +1,20 @@ +// 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> +struct HasFriend { + template <class T> + friend void foo(const HasFriend<T> &m) noexcept(false); +}; + +template <class T> +void foo(const HasFriend<T> &m) noexcept(false) {} + +void f() { + HasFriend<int> x; + foo(x); + bar(x); +} diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp index 1f64ba609b16a..822b1de39a1e3 100644 --- a/test/SemaCXX/friend.cpp +++ b/test/SemaCXX/friend.cpp @@ -162,7 +162,7 @@ namespace test9 { class C { }; struct A { - friend void C::f(int, int, int) {} // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}} + friend void C::f(int, int, int) {} // expected-error {{friend function definition cannot be qualified with 'C::'}} }; } @@ -230,6 +230,10 @@ namespace test10 { friend void f10_d(X); }; + struct W { + friend void f10_d(W); + }; + void g(X x, Y y, Z z) { f10_d(); // expected-error {{undeclared identifier}} ::test10::f10_d(); // expected-error {{no member named 'f10_d'}} @@ -245,14 +249,13 @@ namespace test10 { ::test10::f10_d(z); // expected-error {{no type named 'f10_d'}} } - void local_externs(X x, Y y) { - extern void f10_d(); - extern void f10_d(X); + void local_externs(W w, X x, Y y) { + extern void f10_d(); // expected-note {{candidate}} + extern void f10_d(X); // expected-note {{candidate}} f10_d(); f10_d(x); - // FIXME: This lookup should fail, because the local extern declaration - // should suppress ADL. f10_d(y); + f10_d(w); // expected-error {{no matching}} { int f10_d; f10_d(); // expected-error {{not a function}} @@ -388,3 +391,41 @@ namespace default_arg { friend void f(void *p = 0) {} // expected-error {{must be the only}} }; } + +namespace PR33222 { + int f(); + template<typename T> struct X { + friend T f(); + }; + X<int> xi; + + int g(); // expected-note {{previous}} + template<typename T> struct Y { + friend T g(); // expected-error {{return type}} + }; + Y<float> yf; // expected-note {{instantiation}} + + int h(); // expected-note {{previous}} + template<typename T> struct Z { + friend T h(); // expected-error {{return type}} + }; + Z<int> zi; + Z<float> zf; // expected-note {{instantiation}} +} + +namespace qualified_friend_no_match { + void f(int); // expected-note {{type mismatch at 1st parameter}} + template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}} + struct X { + friend void qualified_friend_no_match::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in namespace 'qualified_friend_no_match'}} + friend void qualified_friend_no_match::g(); // expected-error {{friend declaration of 'g' does not match any declaration in namespace 'qualified_friend_no_match'}} + }; + + struct Y { + void f(int); // expected-note {{type mismatch at 1st parameter}} + template<typename T> void f(T*); // expected-note {{could not match 'type-parameter-0-0 *' against 'double'}} + }; + struct Z { + friend void Y::f(double); // expected-error {{friend declaration of 'f' does not match any declaration in 'qualified_friend_no_match::Y'}} + }; +} diff --git a/test/SemaCXX/friend2.cpp b/test/SemaCXX/friend2.cpp index 8eacdeb19c62e..6d3b545904e48 100644 --- a/test/SemaCXX/friend2.cpp +++ b/test/SemaCXX/friend2.cpp @@ -129,6 +129,83 @@ C22b<int> c22bi; void func_22() {} // expected-error{{redefinition of 'func_22'}} +// Case of template friend functions. + +template<typename T> void func_31(T *x); +template<typename T1> +struct C31a { + template<typename T> friend void func_31(T *x) {} +}; +template<typename T1> +struct C31b { + template<typename T> friend void func_31(T *x) {} +}; + + +template<typename T> inline void func_32(T *x) {} +template<typename T1> +struct C32a { + template<typename T> friend void func_32(T *x) {} +}; +template<typename T1> +struct C32b { + template<typename T> friend void func_32(T *x) {} +}; + + +template<typename T1> +struct C33a { + template<typename T> friend void func_33(T *x) {} +}; +template<typename T1> +struct C33b { + template<typename T> friend void func_33(T *x) {} +}; + + +template<typename T> inline void func_34(T *x) {} // expected-note{{previous definition is here}} +template<typename T1> +struct C34 { + template<typename T> friend void func_34(T *x) {} // expected-error{{redefinition of 'func_34'}} +}; + +C34<int> v34; // expected-note{{in instantiation of template class 'C34<int>' requested here}} + + +template<typename T> inline void func_35(T *x); +template<typename T1> +struct C35a { + template<typename T> friend void func_35(T *x) {} // expected-note{{previous definition is here}} +}; +template<typename T1> +struct C35b { + template<typename T> friend void func_35(T *x) {} // expected-error{{redefinition of 'func_35'}} +}; + +C35a<int> v35a; +C35b<int> v35b; // expected-note{{in instantiation of template class 'C35b<int>' requested here}} + + +template<typename T> void func_36(T *x); +template<typename T1> +struct C36 { + template<typename T> friend void func_36(T *x) {} // expected-error{{redefinition of 'func_36'}} + // expected-note@-1{{previous definition is here}} +}; + +C36<int> v36a; +C36<long> v36b; //expected-note{{in instantiation of template class 'C36<long>' requested here}} + + +template<typename T> void func_37(T *x); +template<typename T1> +struct C37 { + template<typename T> friend void func_37(T *x) {} // expected-note{{previous definition is here}} +}; + +C37<int> v37; +template<typename T> void func_37(T *x) {} // expected-error{{redefinition of 'func_37'}} + namespace pr22307 { @@ -235,3 +312,15 @@ void func() { cache.insert(); } } + +namespace PR39742 { +template<typename> +struct wrapper { + template<typename> + friend void friend_function_template() {} // expected-error{{redefinition of 'friend_function_template'}} + // expected-note@-1{{previous definition is here}} +}; + +wrapper<bool> x; +wrapper<int> y; // expected-note{{in instantiation of template class 'PR39742::wrapper<int>' requested here}} +} diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp index c21f773e94c66..19d645d6d3d15 100644 --- a/test/SemaCXX/implicit-exception-spec.cpp +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -16,41 +16,39 @@ namespace InClassInitializers { // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept()) // is false. bool ThrowSomething() noexcept(false); - struct ConstExpr { + struct ConstExpr { // expected-error {{default member initializer for 'b' needed}} bool b = // expected-note {{declared here}} - noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{default member initializer for 'b' needed}} + noexcept(ConstExpr()) && ThrowSomething(); // expected-note {{in evaluation of exception spec}} }; // Much more obviously broken: we can't parse the initializer without already // knowing whether it produces a noexcept expression. - struct TemplateArg { + struct TemplateArg { // expected-error {{default member initializer for 'n' needed}} int n = // expected-note {{declared here}} - ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{default member initializer for 'n' needed}} + ExceptionIf<noexcept(TemplateArg())>::f(); // expected-note {{in evaluation of exception spec}} }; // And within a nested class. struct Nested { - struct Inner { + struct Inner { // expected-error {{default member initializer for 'n' needed}} int n = // expected-note {{declared here}} - ExceptionIf<noexcept(Nested())>::f(); - } inner; // expected-error {{default member initializer for 'n' needed}} + ExceptionIf<noexcept(Nested())>::f(); // expected-note {{in evaluation of exception spec}} + } inner; // expected-note {{in evaluation of exception spec}} }; struct Nested2 { struct Inner; - int n = Inner().n; // expected-error {{initializer for 'n' needed}} - struct Inner { + int n = Inner().n; // expected-note {{in evaluation of exception spec}} + struct Inner { // expected-error {{initializer for 'n' needed}} int n = ExceptionIf<noexcept(Nested2())>::f(); // expected-note {{declared here}} } inner; }; } namespace ExceptionSpecification { - // FIXME: This diagnostic is quite useless; we should indicate whose - // exception specification we were looking for and why. struct Nested { struct T { - T() noexcept(!noexcept(Nested())); + T() noexcept(!noexcept(Nested())); // expected-note {{in evaluation of exception spec}} } t; // expected-error{{exception specification is not available until end of class definition}} }; } diff --git a/test/SemaCXX/lambda-invalid-capture.cpp b/test/SemaCXX/lambda-invalid-capture.cpp new file mode 100644 index 0000000000000..32349704caa20 --- /dev/null +++ b/test/SemaCXX/lambda-invalid-capture.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// Don't crash. + +struct g { + j; // expected-error {{C++ requires a type specifier for all declarations}} +}; + +void captures_invalid_type() { + g child; + auto q = [child]{}; + const int n = sizeof(q); +} + +void captures_invalid_array_type() { + g child[100]; + auto q = [child]{}; + const int n = sizeof(q); +} diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 8a13eca2f1771..2c4659afa3e74 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -13,10 +13,10 @@ public: bool b(); int k; -struct Recurse { +struct Recurse { // expected-error {{initializer for 'n' needed}} int &n = // expected-note {{declared here}} b() ? - Recurse().n : // expected-error {{initializer for 'n' needed}} + Recurse().n : // expected-note {{in evaluation of exception spec}} k; }; @@ -127,19 +127,19 @@ A::A() {} namespace template_default_ctor { struct A { template <typename T> - struct B { + struct B { // expected-error {{initializer for 'm1' needed}} int m1 = 0; // expected-note {{declared here}} }; - enum { NOE = noexcept(B<int>()) }; // expected-error {{initializer for 'm1' needed}} + enum { NOE = noexcept(B<int>()) }; // expected-note {{in evaluation of exception spec}} }; } namespace default_ctor { struct A { - struct B { + struct B { // expected-error {{initializer for 'm1' needed}} int m1 = 0; // expected-note {{declared here}} }; - enum { NOE = noexcept(B()) }; // expected-error {{initializer for 'm1' needed}} + enum { NOE = noexcept(B()) }; // expected-note {{in evaluation of exception spec}} }; } @@ -147,17 +147,17 @@ namespace member_template { struct A { template <typename T> struct B { - struct C { + struct C { // expected-error {{initializer for 'm1' needed}} int m1 = 0; // expected-note {{declared here}} }; template <typename U> - struct D { + struct D { // expected-error {{initializer for 'm1' needed}} int m1 = 0; // expected-note {{declared here}} }; }; enum { - NOE1 = noexcept(B<int>::C()), // expected-error {{initializer for 'm1' needed}} - NOE2 = noexcept(B<int>::D<int>()) // expected-error {{initializer for 'm1' needed}} + NOE1 = noexcept(B<int>::C()), // expected-note {{in evaluation of exception spec}} + NOE2 = noexcept(B<int>::D<int>()) // expected-note {{in evaluation of exception spec}} }; }; } diff --git a/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp b/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp index 5a399aa7eac22..000492e0edf19 100644 --- a/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp +++ b/test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp @@ -6,8 +6,8 @@ struct S { void operator delete(void*, double); } s; // expected-error {{attempt to use a deleted function}} -struct T { // expected-note{{virtual destructor requires an unambiguous, accessible 'operator delete'}} - virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} +struct T { // expected-note 2{{virtual destructor requires an unambiguous, accessible 'operator delete'}} + virtual ~T() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} expected-warning {{implicitly deleted}} void operator delete(void*, int); void operator delete(void*, double); } t; // expected-error {{attempt to use a deleted function}} diff --git a/test/SemaCXX/microsoft-varargs.cpp b/test/SemaCXX/microsoft-varargs.cpp index 5b0f90eb5ca04..311ce4a54f1fa 100644 --- a/test/SemaCXX/microsoft-varargs.cpp +++ b/test/SemaCXX/microsoft-varargs.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -fsyntax-only %s -verify +// RUN: %clang_cc1 -triple aarch64-windows -fms-compatibility -fsyntax-only %s -verify // expected-no-diagnostics extern "C" { diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp index 624ac0541db46..c177570682f6b 100644 --- a/test/SemaCXX/ms-uuid.cpp +++ b/test/SemaCXX/ms-uuid.cpp @@ -62,14 +62,14 @@ class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2; [uuid("220000A0-0000-0000-C000-000000000049")] class C4 {}; // Both cl and clang-cl error out on this: -// expected-note@+1 {{previous uuid specified here}} -class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) // expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) +// expected-note@+1 {{previous uuid specified here}} __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5; -// expected-note@+1 {{previous uuid specified here}} -[uuid("000000A0-0000-0000-C000-000000000049"), // expected-error@+1 {{uuid does not match previous declaration}} +[uuid("000000A0-0000-0000-C000-000000000049"), +// expected-note@+1 {{previous uuid specified here}} uuid("110000A0-0000-0000-C000-000000000049")] class C6; // cl doesn't diagnose having one uuid each as []-style attributes and as diff --git a/test/SemaCXX/multistep-explicit-cast.cpp b/test/SemaCXX/multistep-explicit-cast.cpp deleted file mode 100644 index 58466791354c5..0000000000000 --- a/test/SemaCXX/multistep-explicit-cast.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -ast-dump %s | FileCheck %s - -// We are checking that implicit casts don't get marked with 'part_of_explicit_cast', -// while in explicit casts, the implicitly-inserted implicit casts are marked with 'part_of_explicit_cast' - -unsigned char implicitcast_0(unsigned int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_0 'unsigned char (unsigned int)'{{$}} - // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} - return x; -} - -signed char implicitcast_1(unsigned int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_1 'signed char (unsigned int)'{{$}} - // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue>{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} - return x; -} - -unsigned char implicitcast_2(signed int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_2 'unsigned char (int)'{{$}} - // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} - return x; -} - -signed char implicitcast_3(signed int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} implicitcast_3 'signed char (int)'{{$}} - // CHECK: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue>{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} - return x; -} - -//----------------------------------------------------------------------------// - -unsigned char cstylecast_0(unsigned int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_0 'unsigned char (unsigned int)'{{$}} - // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} - return (unsigned char)x; -} - -signed char cstylecast_1(unsigned int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_1 'signed char (unsigned int)'{{$}} - // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} - return (signed char)x; -} - -unsigned char cstylecast_2(signed int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_2 'unsigned char (int)'{{$}} - // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} - return (unsigned char)x; -} - -signed char cstylecast_3(signed int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cstylecast_3 'signed char (int)'{{$}} - // CHECK: CStyleCastExpr {{.*}} <col:{{.*}}> 'signed char' <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} - return (signed char)x; -} - -//----------------------------------------------------------------------------// - -unsigned char cxxstaticcast_0(unsigned int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_0 'unsigned char (unsigned int)'{{$}} - // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'unsigned char' static_cast<unsigned char> <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} - return static_cast<unsigned char>(x); -} - -signed char cxxstaticcast_1(unsigned int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_1 'signed char (unsigned int)'{{$}} - // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'signed char' static_cast<signed char> <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'unsigned int' lvalue ParmVar {{.*}} 'x' 'unsigned int'{{$}} - return static_cast<signed char>(x); -} - -unsigned char cxxstaticcast_2(signed int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_2 'unsigned char (int)'{{$}} - // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'unsigned char' static_cast<unsigned char> <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'unsigned char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} - return static_cast<unsigned char>(x); -} - -signed char cxxstaticcast_3(signed int x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxstaticcast_3 'signed char (int)'{{$}} - // CHECK: CXXStaticCastExpr {{.*}} <col:{{.*}}> 'signed char' static_cast<signed char> <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'signed char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue ParmVar {{.*}} 'x' 'int'{{$}} - return static_cast<signed char>(x); -} - -//----------------------------------------------------------------------------// - -using UnsignedChar = unsigned char; -using SignedChar = signed char; -using UnsignedInt = unsigned int; -using SignedInt = signed int; - -UnsignedChar cxxfunctionalcast_0(UnsignedInt x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_0 'UnsignedChar (UnsignedInt)'{{$}} - // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' functional cast to UnsignedChar <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}} - return UnsignedChar(x); -} - -SignedChar cxxfunctionalcast_1(UnsignedInt x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_1 'SignedChar (UnsignedInt)'{{$}} - // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' functional cast to SignedChar <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'UnsignedInt':'unsigned int' lvalue ParmVar {{.*}} 'x' 'UnsignedInt':'unsigned int'{{$}} - return SignedChar(x); -} - -UnsignedChar cxxfunctionalcast_2(SignedInt x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_2 'UnsignedChar (SignedInt)'{{$}} - // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' functional cast to UnsignedChar <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'UnsignedChar':'unsigned char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}} - return UnsignedChar(x); -} - -SignedChar cxxfunctionalcast_3(SignedInt x) { - // CHECK: FunctionDecl {{.*}} <{{.*}}, line:{{.*}}> line:{{.*}} cxxfunctionalcast_3 'SignedChar (SignedInt)'{{$}} - // CHECK: CXXFunctionalCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' functional cast to SignedChar <NoOp>{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedChar':'signed char' <IntegralCast> part_of_explicit_cast{{$}} - // CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' <LValueToRValue> part_of_explicit_cast{{$}} - // CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'SignedInt':'int' lvalue ParmVar {{.*}} 'x' 'SignedInt':'int'{{$}} - return SignedChar(x); -} diff --git a/test/SemaCXX/no_destroy.cpp b/test/SemaCXX/no_destroy.cpp new file mode 100644 index 0000000000000..7afbf99982530 --- /dev/null +++ b/test/SemaCXX/no_destroy.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -DNO_DTORS -fno-c++-static-destructors -verify %s +// RUN: %clang_cc1 -verify %s + +struct SecretDestructor { +#ifndef NO_DTORS + // expected-note@+2 4 {{private}} +#endif +private: ~SecretDestructor(); // expected-note 2 {{private}} +}; + +SecretDestructor sd1; +thread_local SecretDestructor sd2; +void locals() { + static SecretDestructor sd3; + thread_local SecretDestructor sd4; +} + +#ifndef NO_DTORS +// SecretDestructor sd1; // expected-error@-8 {{private}} +// thread_local SecretDestructor sd2; // expected-error@-8 {{private}} +// void locals() { +// static SecretDestructor sd3; // expected-error@-8 {{private}} +// thread_local SecretDestructor sd4; // expected-error@-8 {{private}} +// } +#endif + +[[clang::always_destroy]] SecretDestructor sd6; // expected-error{{private}} +[[clang::always_destroy]] thread_local SecretDestructor sd7; // expected-error{{private}} + +[[clang::no_destroy]] SecretDestructor sd8; + +int main() { + [[clang::no_destroy]] int p; // expected-error{{no_destroy attribute can only be applied to a variable with static or thread storage duration}} + [[clang::always_destroy]] int p2; // expected-error{{always_destroy attribute can only be applied to a variable with static or thread storage duration}} + [[clang::no_destroy]] static int p3; + [[clang::always_destroy]] static int p4; +} + +[[clang::always_destroy]] [[clang::no_destroy]] int p; // expected-error{{'no_destroy' and 'always_destroy' attributes are not compatible}} // expected-note{{here}} +[[clang::no_destroy]] [[clang::always_destroy]] int p2; // expected-error{{'always_destroy' and 'no_destroy' attributes are not compatible}} // expected-note{{here}} + +[[clang::always_destroy]] void f() {} // expected-warning{{'always_destroy' attribute only applies to variables}} +struct [[clang::no_destroy]] DoesntApply {}; // expected-warning{{'no_destroy' attribute only applies to variables}} + +[[clang::no_destroy(0)]] int no_args; // expected-error{{'no_destroy' attribute takes no arguments}} +[[clang::always_destroy(0)]] int no_args2; // expected-error{{'always_destroy' attribute takes no arguments}} diff --git a/test/SemaCXX/rdar42746401.cpp b/test/SemaCXX/rdar42746401.cpp new file mode 100644 index 0000000000000..ff9dff456ce47 --- /dev/null +++ b/test/SemaCXX/rdar42746401.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <int> +class b; +class c; // expected-note{{forward declaration}} + +::b<0> struct c::d // expected-error{{incomplete type}} expected-error{{cannot combine}} expected-error{{expected unqualified-id}} diff --git a/test/SemaCXX/sourceranges.cpp b/test/SemaCXX/sourceranges.cpp deleted file mode 100644 index 58772a063915d..0000000000000 --- a/test/SemaCXX/sourceranges.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s
-// RUN: %clang_cc1 -triple i686-mingw32 -std=c++1z -ast-dump %s | FileCheck %s -check-prefix=CHECK-1Z
-
-template<class T>
-class P {
- public:
- P(T* t) {}
-};
-
-namespace foo {
-class A { public: A(int = 0) {} };
-enum B {};
-typedef int C;
-}
-
-// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:[[@LINE+1]]:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'
-static foo::A ImplicitConstrArray[2];
-
-int main() {
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::A *'
- P<foo::A> p14 = new foo::A;
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::B *'
- P<foo::B> p24 = new foo::B;
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::C *'
- P<foo::C> pr4 = new foo::C;
-}
-
-foo::A getName() {
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A'
- return foo::A();
-}
-
-void destruct(foo::A *a1, foo::A *a2, P<int> *p1) {
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:8> '<bound member function type>' ->~A
- a1->~A();
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:16> '<bound member function type>' ->~A
- a2->foo::A::~A();
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:13> '<bound member function type>' ->~P
- p1->~P<int>();
-}
-
-struct D {
- D(int);
- ~D();
-};
-
-void construct() {
- using namespace foo;
- A a = A(12);
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'foo::A' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
- D d = D(12);
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
-}
-
-void abort() __attribute__((noreturn));
-
-namespace std {
-typedef decltype(sizeof(int)) size_t;
-
-template <typename E> struct initializer_list {
- const E *p;
- size_t n;
- initializer_list(const E *p, size_t n) : p(p), n(n) {}
-};
-
-template <typename F, typename S> struct pair {
- F f;
- S s;
- pair(const F &f, const S &s) : f(f), s(s) {}
-};
-
-struct string {
- const char *str;
- string() { abort(); }
- string(const char *S) : str(S) {}
- ~string() { abort(); }
-};
-
-template<typename K, typename V>
-struct map {
- using T = pair<K, V>;
- map(initializer_list<T> i, const string &s = string()) {}
- ~map() { abort(); }
-};
-
-}; // namespace std
-
-#if __cplusplus >= 201703L
-// CHECK-1Z: FunctionDecl {{.*}} construct_with_init_list
-std::map<int, int> construct_with_init_list() {
- // CHECK-1Z-NEXT: CompoundStmt
- // CHECK-1Z-NEXT: ReturnStmt {{.*}} <line:[[@LINE+5]]:3, col:35
- // CHECK-1Z-NEXT: ExprWithCleanups {{.*}} <col:10, col:35
- // CHECK-1Z-NEXT: CXXBindTemporaryExpr {{.*}} <col:10, col:35
- // CHECK-1Z-NEXT: CXXTemporaryObjectExpr {{.*}} <col:10, col:35
- // CHECK-1Z-NEXT: CXXStdInitializerListExpr {{.*}} <col:28, col:35
- return std::map<int, int>{{0, 0}};
-}
-
-// CHECK-1Z: NamespaceDecl {{.*}} in_class_init
-namespace in_class_init {
- struct A {};
-
- // CHECK-1Z: CXXRecordDecl {{.*}} struct B definition
- struct B {
- // CHECK-1Z: FieldDecl {{.*}} a 'in_class_init::A'
- // CHECK-1Z-NEXT: InitListExpr {{.*}} <col:11, col:12
- A a = {};
- };
-}
-
-// CHECK-1Z: NamespaceDecl {{.*}} delegating_constructor_init
-namespace delegating_constructor_init {
- struct A {};
-
- struct B : A {
- A a;
- B(A a) : a(a) {}
- };
-
- // CHECK-1Z: CXXRecordDecl {{.*}} struct C definition
- struct C : B {
- // CHECK-1Z: CXXConstructorDecl {{.*}} C
- // CHECK-1Z-NEXT: CXXCtorInitializer 'delegating_constructor_init::B'
- // CHECK-1Z-NEXT: CXXConstructExpr {{.*}} <col:11, col:15
- // CHECK-1Z-NEXT: InitListExpr {{.*}} <col:13, col:14
- C() : B({}) {};
- };
-}
-
-// CHECK-1Z: NamespaceDecl {{.*}} new_init
-namespace new_init {
- void A() {
- // CHECK-1Z: CXXNewExpr {{.*}} <line:[[@LINE+2]]:5, col:14
- // CHECK-1Z-NEXT: InitListExpr {{.*}} <col:12, col:14
- new int{0};
- }
-}
-#endif
diff --git a/test/SemaCXX/static-assert-cxx17.cpp b/test/SemaCXX/static-assert-cxx17.cpp new file mode 100644 index 0000000000000..fe02f8f29965f --- /dev/null +++ b/test/SemaCXX/static-assert-cxx17.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z -triple=x86_64-linux-gnu + +template <typename U, typename V> +struct S1 { + static constexpr const bool value = false; +}; + +template <typename U, typename V> +inline constexpr bool global_inline_var = S1<U, V>::value; + +template <typename T> +struct S2 { + template <typename U, typename V> + static inline constexpr bool var = global_inline_var<U, V>; +}; + +template <typename U, typename V> +inline constexpr bool constexpr_return_false() { + return false; +} + +template <typename U, typename V> +void foo() { + static_assert(S1<U, V>::value); + // expected-error@-1{{static_assert failed due to requirement 'S1<int, float>::value'}} +} +template void foo<int, float>(); +// expected-note@-1{{in instantiation of function template specialization 'foo<int, float>' requested here}} + +template <typename U, typename V> +void foo2() { + static_assert(global_inline_var<U, V>); + // expected-error@-1{{static_assert failed due to requirement 'global_inline_var<int, float>'}} +} +template void foo2<int, float>(); +// expected-note@-1{{in instantiation of function template specialization 'foo2<int, float>' requested here}} + +template <typename T, typename U, typename V> +void foo3() { + static_assert(T::template var<U, V>); + // expected-error@-1{{static_assert failed due to requirement 'S2<long>::var<int, float>'}} +} +template void foo3<S2<long>, int, float>(); +// expected-note@-1{{in instantiation of function template specialization 'foo3<S2<long>, int, float>' requested here}} + +template <typename T> +void foo4() { + static_assert(S1<T[sizeof(T)], int[4]>::value, ""); + // expected-error@-1{{static_assert failed due to requirement 'S1<float [4], int [4]>::value'}} +}; +template void foo4<float>(); +// expected-note@-1{{in instantiation of function template specialization 'foo4<float>' requested here}} + + +template <typename U, typename V> +void foo5() { + static_assert(!!(global_inline_var<U, V>)); + // expected-error@-1{{static_assert failed due to requirement '!!(global_inline_var<int, float>)'}} +} +template void foo5<int, float>(); +// expected-note@-1{{in instantiation of function template specialization 'foo5<int, float>' requested here}} + +struct ExampleTypes { + explicit ExampleTypes(int); + using T = int; + using U = float; +}; + +template <class T> +struct X { + int i = 0; + int j = 0; + constexpr operator bool() const { return false; } +}; + +template <class T> +void foo6() { + static_assert(X<typename T::T>()); + // expected-error@-1{{static_assert failed due to requirement 'X<int>()'}} + static_assert(X<typename T::T>{}); + // expected-error@-1{{static_assert failed due to requirement 'X<int>{}'}} + static_assert(X<typename T::T>{1, 2}); + // expected-error@-1{{static_assert failed due to requirement 'X<int>{1, 2}'}} + static_assert(X<typename T::T>({1, 2})); + // expected-error@-1{{static_assert failed due to requirement 'X<int>({1, 2})'}} + static_assert(typename T::T{0}); + // expected-error@-1{{static_assert failed due to requirement 'int{0}'}} + static_assert(typename T::T(0)); + // expected-error@-1{{static_assert failed due to requirement 'int(0)'}} + static_assert(sizeof(X<typename T::T>) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<int>) == 0'}} + static_assert((const X<typename T::T> *)nullptr); + // expected-error@-1{{static_assert failed due to requirement '(const X<int> *)nullptr'}} + static_assert(static_cast<const X<typename T::T> *>(nullptr)); + // expected-error@-1{{static_assert failed due to requirement 'static_cast<const X<int> *>(nullptr)'}} + static_assert((const X<typename T::T>[]){} == nullptr); + // expected-error@-1{{static_assert failed due to requirement '(X<int> const[0]){} == nullptr'}} + static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0); + // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<void>) == 0'}} + static_assert(constexpr_return_false<typename T::T, typename T::U>()); + // expected-error@-1{{static_assert failed due to requirement 'constexpr_return_false<int, float>()'}} +} +template void foo6<ExampleTypes>(); +// expected-note@-1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}} diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp index 846303807a023..a21cc874b566e 100644 --- a/test/SemaCXX/static-assert.cpp +++ b/test/SemaCXX/static-assert.cpp @@ -15,14 +15,14 @@ class C { }; template<int N> struct T { - static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}} + static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed due to requirement '1 == 2' "N is not 2!"}} }; T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}} T<2> t2; template<typename T> struct S { - static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}} + static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed due to requirement 'sizeof(char) > sizeof(char)' "Type not big enough!"}} }; S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}} @@ -68,3 +68,123 @@ template<typename T> struct second_trait { }; static_assert(first_trait<X>::value && second_trait<X>::value, "message"); // expected-error{{static_assert failed due to requirement 'second_trait<X>::value' "message"}} + +namespace std { + +template <class Tp, Tp v> +struct integral_constant { + static const Tp value = v; + typedef Tp value_type; + typedef integral_constant type; + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } +}; + +template <class Tp, Tp v> +const Tp integral_constant<Tp, v>::value; + +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; + +template <class Tp> +struct is_const : public false_type {}; +template <class Tp> +struct is_const<Tp const> : public true_type {}; + +// We do not define is_same in terms of integral_constant to check that both implementations are supported. +template <typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template <typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +} // namespace std + +struct ExampleTypes { + explicit ExampleTypes(int); + using T = int; + using U = float; +}; + +static_assert(std::is_same<ExampleTypes::T, ExampleTypes::U>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_same<int, float>::value' "message"}} +static_assert(std::is_const<ExampleTypes::T>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}} +static_assert(!std::is_const<const ExampleTypes::T>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement '!std::is_const<const int>::value' "message"}} +static_assert(!(std::is_const<const ExampleTypes::T>::value), "message"); +// expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>::value)' "message"}} +static_assert(std::is_const<const ExampleTypes::T>::value == false, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const<const int>::value == false' "message"}} +static_assert(!(std::is_const<const ExampleTypes::T>::value == true), "message"); +// expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>::value == true)' "message"}} +static_assert(std::is_const<ExampleTypes::T>(), "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>()' "message"}} +static_assert(!(std::is_const<const ExampleTypes::T>()()), "message"); +// expected-error@-1{{static_assert failed due to requirement '!(std::is_const<const int>()())' "message"}} +static_assert(std::is_same<decltype(std::is_const<const ExampleTypes::T>()), int>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_same<std::is_const<const int>, int>::value' "message"}} +static_assert(std::is_const<decltype(ExampleTypes::T(3))>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}} +static_assert(std::is_const<decltype(ExampleTypes::T())>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}} +static_assert(std::is_const<decltype(ExampleTypes(3))>::value, "message"); +// expected-error@-1{{static_assert failed due to requirement 'std::is_const<ExampleTypes>::value' "message"}} + +struct BI_tag {}; +struct RAI_tag : BI_tag {}; +struct MyIterator { + using tag = BI_tag; +}; +struct MyContainer { + using iterator = MyIterator; +}; +template <class Container> +void foo() { + static_assert(std::is_same<RAI_tag, typename Container::iterator::tag>::value, "message"); + // expected-error@-1{{static_assert failed due to requirement 'std::is_same<RAI_tag, BI_tag>::value' "message"}} +} +template void foo<MyContainer>(); +// expected-note@-1{{in instantiation of function template specialization 'foo<MyContainer>' requested here}} + +namespace ns { +template <typename T, int v> +struct NestedTemplates1 { + struct NestedTemplates2 { + template <typename U> + struct NestedTemplates3 : public std::is_same<T, U> {}; + }; +}; +} // namespace ns + +template <typename T, typename U, int a> +void foo2() { + static_assert(::ns::NestedTemplates1<T, a>::NestedTemplates2::template NestedTemplates3<U>::value, "message"); + // expected-error@-1{{static_assert failed due to requirement '::ns::NestedTemplates1<int, 3>::NestedTemplates2::NestedTemplates3<float>::value' "message"}} +} +template void foo2<int, float, 3>(); +// expected-note@-1{{in instantiation of function template specialization 'foo2<int, float, 3>' requested here}} + +template <class T> +void foo3(T t) { + static_assert(std::is_const<T>::value, "message"); + // expected-error-re@-1{{static_assert failed due to requirement 'std::is_const<(lambda at {{.*}}static-assert.cpp:{{[0-9]*}}:{{[0-9]*}})>::value' "message"}} + static_assert(std::is_const<decltype(t)>::value, "message"); + // expected-error-re@-1{{static_assert failed due to requirement 'std::is_const<(lambda at {{.*}}static-assert.cpp:{{[0-9]*}}:{{[0-9]*}})>::value' "message"}} +} +void callFoo3() { + foo3([]() {}); + // expected-note@-1{{in instantiation of function template specialization 'foo3<(lambda at }} +} + +template <class T> +void foo4(T t) { + static_assert(std::is_const<typename T::iterator>::value, "message"); + // expected-error@-1{{type 'int' cannot be used prior to '::' because it has no members}} +} +void callFoo4() { foo4(42); } +// expected-note@-1{{in instantiation of function template specialization 'foo4<int>' requested here}} diff --git a/test/SemaCXX/string-plus-int.cpp b/test/SemaCXX/string-plus-int.cpp index fe9c719496986..448fb49fb49f0 100644 --- a/test/SemaCXX/string-plus-int.cpp +++ b/test/SemaCXX/string-plus-int.cpp @@ -31,37 +31,36 @@ void f(int index) { consume("foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consume("foo" + index); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consume("foo" + kMyEnum); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume("foo" + kMySmallEnum); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consume(5 + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consume(index + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consume(kMyEnum + "foo"); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume(kMySmallEnum + "foo"); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} // FIXME: suggest replacing with "foo"[5] consumeChar(*("foo" + 5)); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consumeChar(*(5 + "foo")); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} consume(L"foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume(L"foo" + 2); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + + consume("foo" + 3); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume("foo" + 4); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume("\pfoo" + 4); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + + #define A "foo" + #define B "bar" + consume(A B + sizeof(A) - 1); // expected-warning {{to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} // Should not warn. consume(&("foo"[3])); consume(&("foo"[index])); consume(&("foo"[kMyEnum])); - consume("foo" + kMySmallEnum); - consume(kMySmallEnum + "foo"); - consume(L"foo" + 2); - - consume("foo" + 3); // Points at the \0 - consume("foo" + 4); // Points 1 past the \0, which is legal too. - consume("\pfoo" + 4); // Pascal strings don't have a trailing \0, but they - // have a leading length byte, so this is fine too. consume("foo" + kMyOperatorOverloadedEnum); consume(kMyOperatorOverloadedEnum + "foo"); - - #define A "foo" - #define B "bar" - consume(A B + sizeof(A) - 1); } template <typename T> diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp index 7375319186a1d..622d5a0b652a7 100644 --- a/test/SemaCXX/struct-class-redecl.cpp +++ b/test/SemaCXX/struct-class-redecl.cpp @@ -47,14 +47,43 @@ class E; struct F; struct F; -struct F {}; +struct F {}; // expected-note {{previous use}} struct F; +class F; // expected-warning {{previously declared as a struct}} expected-note {{did you mean struct}} template<class U> class G; // expected-note{{previous use is here}}\ // expected-note{{did you mean struct here?}} template<class U> struct G; // expected-warning{{struct template 'G' was previously declared as a class template}} template<class U> struct G {}; // expected-warning{{'G' defined as a struct template here but previously declared as a class template}} +// Declarations from contexts where the warning is disabled are entirely +// ignored for the purpose of this warning. +struct J; +struct K; // expected-note {{previous use}} +struct L; +struct M; // expected-note {{previous use}} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" +struct H; +class I {}; +class J; +class K; +class L; +class M {}; +#pragma clang diagnostic pop + +class H; // expected-note {{previous use}} +struct H; // expected-warning {{previously declared as a class}} + +struct I; // expected-note {{previous use}} +class I; // expected-warning {{previously declared as a struct}} + +struct J; +class K; // expected-warning {{previously declared as a struct}} +struct L; +class M; // expected-warning {{previously declared as a struct}} + /* *** 'X' messages *** CHECK: warning: struct 'X' was previously declared as a class diff --git a/test/SemaCXX/subst-restrict.cpp b/test/SemaCXX/subst-restrict.cpp new file mode 100644 index 0000000000000..aab6872d8de8a --- /dev/null +++ b/test/SemaCXX/subst-restrict.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++17 -verify %s + +// expected-no-diagnostics + +template <class T> struct add_restrict { + typedef T __restrict type; +}; + +template <class T, class V> struct is_same { + static constexpr bool value = false; +}; + +template <class T> struct is_same<T, T> { + static constexpr bool value = true; +}; + +static_assert(is_same<int & __restrict, add_restrict<int &>::type>::value, ""); +static_assert(is_same<int(), add_restrict<int()>::type>::value, ""); diff --git a/test/SemaCXX/switch-implicit-fallthrough.cpp b/test/SemaCXX/switch-implicit-fallthrough.cpp index 9540b1ff28808..6ccac122cff73 100644 --- a/test/SemaCXX/switch-implicit-fallthrough.cpp +++ b/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -314,3 +314,18 @@ int fallthrough_targets(int n) { } return n; } + +int fallthrough_alt_spelling(int n) { + switch (n) { + case 0: + n++; + [[clang::fallthrough]]; + case 1: + n++; + [[clang::__fallthrough__]]; + case 2: + n++; + break; + } + return n; +} diff --git a/test/SemaCXX/template-implicit-vars.cpp b/test/SemaCXX/template-implicit-vars.cpp deleted file mode 100644 index 25d35fbdb84f5..0000000000000 --- a/test/SemaCXX/template-implicit-vars.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -ast-dump | FileCheck %s -template<typename T> -void f(T t) { - T a[] = {t}; - for (auto x : a) {} -} - -void g() { - f(1); -} -// CHECK: VarDecl {{.*}} implicit used __range -// CHECK: VarDecl {{.*}} implicit used __range -// CHECK: VarDecl {{.*}} implicit used __begin -// CHECK: VarDecl {{.*}} implicit used __end diff --git a/test/SemaCXX/thread-safety-annotations.h b/test/SemaCXX/thread-safety-annotations.h new file mode 100644 index 0000000000000..7755a1b328e7e --- /dev/null +++ b/test/SemaCXX/thread-safety-annotations.h @@ -0,0 +1,42 @@ +// Macros to enable testing of both variants of the thread safety analysis. + +#if USE_CAPABILITY +#define LOCKABLE __attribute__((capability("mutex"))) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) +#else +#define LOCKABLE __attribute__((lockable)) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) +#endif + +// Lock semantics only +#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#define GUARDED_VAR __attribute__((guarded_var)) +#define PT_GUARDED_VAR __attribute__((pt_guarded_var)) + +// Capabilities only +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) +#define GUARDED_BY(x) __attribute__((guarded_by(x))) +#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x))) + +// Common +#define SCOPED_LOCKABLE __attribute__((scoped_lockable)) +#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) +#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) +#define LOCK_RETURNED(x) __attribute__((lock_returned(x))) +#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) +#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) diff --git a/test/SemaCXX/unavailable_aligned_allocation.cpp b/test/SemaCXX/unavailable_aligned_allocation.cpp index 2000e0b6a319a..2f0f8fe7a4b50 100644 --- a/test/SemaCXX/unavailable_aligned_allocation.cpp +++ b/test/SemaCXX/unavailable_aligned_allocation.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify %s -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -fexceptions -faligned-allocation -faligned-alloc-unavailable -std=c++14 -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13.0 -fexceptions -faligned-allocation -faligned-alloc-unavailable -std=c++14 -verify %s // RUN: %clang_cc1 -triple arm64-apple-ios10.0.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify -DIOS %s // RUN: %clang_cc1 -triple arm64-apple-ios10.0.0 -fexceptions -std=c++1z -verify -DNO_ERRORS %s // RUN: %clang_cc1 -triple arm64-apple-tvos10.0.0 -fexceptions -faligned-alloc-unavailable -std=c++1z -verify -DTVOS %s @@ -117,13 +117,80 @@ void testOveralignedCheckOS() { // expected-error@-13 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on watchOS 4 or newer}}} // expected-error@-14 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}} #else -// expected-error@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on macOS 10.13 or newer}}} -// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.13 or newer}}} +// expected-error@-16 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on macOS 10.14 or newer}}} +// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.14 or newer}}} #endif // expected-note@-20 2 {{if you supply your own aligned allocation functions}} #endif +// Test that diagnostics are produced when an unavailable aligned deallocation +// function is called from a deleting destructor. +struct alignas(256) OveralignedS2 { + int a[4]; + virtual ~OveralignedS2(); +}; + +OveralignedS2::~OveralignedS2() {} + +#ifdef NO_ERRORS +// expected-no-diagnostics +#else +#if defined(IOS) +// expected-error@-6 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on iOS 11 or newer}}} +// expected-note@-7 {{if you supply your own aligned allocation functions}} +#elif defined(TVOS) +// expected-error@-9 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on tvOS 11 or newer}}} +// expected-note@-10 {{if you supply your own aligned allocation functions}} +#elif defined(WATCHOS) +// expected-error@-12 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on watchOS 4 or newer}}} +// expected-note@-13 {{if you supply your own aligned allocation functions}} +#else +// expected-error@-15 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.14 or newer}}} +// expected-note@-16 {{if you supply your own aligned allocation functions}} +#endif +#endif + +void testExplicitOperatorNewDelete() { + void *p = operator new(128); + operator delete(p); + p = operator new[](128); + operator delete[](p); + p = __builtin_operator_new(128); + __builtin_operator_delete(p); +} + +void testExplicitOperatorNewDeleteOveraligned() { + void *p = operator new(128, (std::align_val_t)64); + operator delete(p, (std::align_val_t)64); + p = operator new[](128, (std::align_val_t)64); + operator delete[](p, (std::align_val_t)64); + p = __builtin_operator_new(128, (std::align_val_t)64); + __builtin_operator_delete(p, (std::align_val_t)64); +} + +#ifdef NO_ERRORS +// expected-no-diagnostics +#else +// expected-error@-11 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}} +// expected-note@-12 {{if you supply your own aligned allocation functions}} + +// expected-error@-13 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}} +// expected-note@-14 {{if you supply your own aligned allocation functions}} + +// expected-error@-15 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}} +// expected-note@-16 {{if you supply your own aligned allocation functions}} + +// expected-error@-17 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}} +// expected-note@-18 {{if you supply your own aligned allocation functions}} + +// expected-error@-19 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is only available on}} +// expected-note@-20 {{if you supply your own aligned allocation functions}} + +// expected-error@-21 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on}} +// expected-note@-22 {{if you supply your own aligned allocation functions}} +#endif + // No errors if user-defined aligned allocation functions are available. void *operator new(std::size_t __sz, std::align_val_t) { static char array[256]; diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index f620e1014c349..331a948eb6f1d 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -884,8 +884,10 @@ namespace lambdas { int x; }; A a0([] { return a0.x; }); // ok - void f() { - A a1([=] { return a1.x; }); // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}} + void f() { + A a1([=] { // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}} + return a1.x; + }); A a2([&] { return a2.x; }); // ok } } diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 56a8a6db5b68c..a6a4ceb0e535f 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -17,14 +17,14 @@ void f0_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { f0(ll16e); } -int &f1(char16); // expected-note 2{{candidate function}} -float &f1(longlong16); // expected-note 2{{candidate function}} +int &f1(char16); +float &f1(longlong16); void f1_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { int &ir1 = f1(c16); float &fr1 = f1(ll16); - f1(c16e); // expected-error{{call to 'f1' is ambiguous}} - f1(ll16e); // expected-error{{call to 'f1' is ambiguous}} + int &ir2 = f1(c16e); + float &fr2 = f1(ll16e); } void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' (vector of 2 'long long' values) to 'char16_e' (vector of 16 'char' values) for 1st argument}} \ diff --git a/test/SemaCXX/warn-comma-operator.cpp b/test/SemaCXX/warn-comma-operator.cpp index 3192f688f1ba0..0ed127b943f39 100644 --- a/test/SemaCXX/warn-comma-operator.cpp +++ b/test/SemaCXX/warn-comma-operator.cpp @@ -1,8 +1,16 @@ // RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -verify %s // RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c89 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c99 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wcomma -x c -std=c17 -verify %s + +// int returning function +int return_four() { return 5; } + // Test builtin operators -void test1() { +void test_builtin() { int x = 0, y = 0; for (; y < 10; x++, y++) {} for (; y < 10; ++x, y++) {} @@ -23,6 +31,116 @@ void test1() { for (; y < 10; x ^= 5, ++y) {} } +// Test nested comma operators +void test_nested() { + int x1, x2, x3; + int y1, *y2 = 0, y3 = 5; + +#if __STDC_VERSION >= 199901L + for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {} +#endif +} + +// Confusing "," for "==" +void test_compare() { + if (return_four(), 5) {} + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")" + + if (return_four() == 5) {} +} + +// Confusing "," for "+" +int test_plus() { + return return_four(), return_four(); + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" + + return return_four() + return_four(); +} + +// Be sure to look through parentheses +void test_parentheses() { + int x, y; + for (x = 0; return_four(), x;) {} + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:28-[[@LINE-4]]:28}:")" + + for (x = 0; (return_four()), (x) ;) {} + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")" +} + +void test_increment() { + int x, y; + ++x, ++y; + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:6-[[@LINE-4]]:6}:")" +} + +// Check for comma operator in conditions. +void test_conditions(int x) { + x = (return_four(), x); + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:8-[[@LINE-3]]:8}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:21-[[@LINE-4]]:21}:")" + + int y = (return_four(), x); + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")" + + for (; return_four(), x;) {} + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" + + while (return_four(), x) {} + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" + + if (return_four(), x) {} + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")" + + do { } while (return_four(), x); + // expected-warning@-1{{comma operator}} + // expected-note@-2{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")" +} + +// Nested comma operator with fix-its. +void test_nested_fixits() { + return_four(), return_four(), return_four(), return_four(); + // expected-warning@-1 3{{comma operator}} + // expected-note@-2 3{{cast expression to void}} + // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:16-[[@LINE-4]]:16}:")" + // CHECK: fix-it:{{.*}}:{[[@LINE-5]]:18-[[@LINE-5]]:18}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-6]]:31-[[@LINE-6]]:31}:")" + // CHECK: fix-it:{{.*}}:{[[@LINE-7]]:33-[[@LINE-7]]:33}:"static_cast<void>(" + // CHECK: fix-it:{{.*}}:{[[@LINE-8]]:46-[[@LINE-8]]:46}:")" +} + +#ifdef __cplusplus class S2 { public: void advance(); @@ -45,7 +163,7 @@ public: }; // Test overloaded operators -void test2() { +void test_overloaded_operator() { S2 x; int y; for (; y < 10; x++, y++) {} @@ -67,22 +185,13 @@ void test2() { for (; y < 10; x ^= 5, ++y) {} } -// Test nested comma operators -void test3() { - int x1, x2, x3; - int y1, *y2 = 0, y3 = 5; - for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {} -} - class Stream { public: Stream& operator<<(int); } cout; -int return_four() { return 5; } - // Confusing "," for "<<" -void test4() { +void test_stream() { cout << 5 << return_four(); cout << 5, return_four(); // expected-warning@-1{{comma operator}} @@ -91,33 +200,11 @@ void test4() { // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:12-[[@LINE-4]]:12}:")" } -// Confusing "," for "==" -void test5() { - if (return_four(), 5) {} - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")" - - if (return_four() == 5) {} -} - -// Confusing "," for "+" -int test6() { - return return_four(), return_four(); - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" - - return return_four() + return_four(); -} - void Concat(int); void Concat(int, int); // Testing extra parentheses in function call -void test7() { +void test_overloaded_function() { Concat((return_four() , 5)); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} @@ -127,22 +214,6 @@ void test7() { Concat(return_four() , 5); } -// Be sure to look through parentheses -void test8() { - int x, y; - for (x = 0; return_four(), x;) {} - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:28-[[@LINE-4]]:28}:")" - - for (x = 0; (return_four()), (x) ;) {} - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")" -} - bool DoStuff(); class S9 { public: @@ -151,24 +222,15 @@ public: }; // Ignore comma operator in for-loop initializations and increments. -void test9() { +void test_for_loop() { int x, y; for (x = 0, y = 5; x < y; ++x) {} for (x = 0; x < 10; DoStuff(), ++x) {} for (S9 s; s.More(); s.Advance(), ++x) {} } -void test10() { - int x, y; - ++x, ++y; - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:6-[[@LINE-4]]:6}:")" -} - // Ignore comma operator in templates. -namespace test11 { +namespace test_template { template <bool T> struct B { static const bool value = T; }; @@ -188,7 +250,7 @@ class Foo { const auto X = Foo<true_type>(); } -namespace test12 { +namespace test_mutex { class Mutex { public: Mutex(); @@ -225,54 +287,13 @@ bool get_status() { } } -// Check for comma operator in conditions. -void test13(int x) { - x = (return_four(), x); - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:8-[[@LINE-3]]:8}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:21-[[@LINE-4]]:21}:")" - - int y = (return_four(), x); - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")" - - for (; return_four(), x;) {} - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" - - while (return_four(), x) {} - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" - - if (return_four(), x) {} - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")" +// PR39375 - test cast to void to silence warnings +template <typename T> +void test_dependent_cast() { + (void)42, 0; + static_cast<void>(42), 0; - do { } while (return_four(), x); - // expected-warning@-1{{comma operator}} - // expected-note@-2{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")" -} - -// Nested comma operator with fix-its. -void test14() { - return_four(), return_four(), return_four(), return_four(); - // expected-warning@-1 3{{comma operator}} - // expected-note@-2 3{{cast expression to void}} - // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:16-[[@LINE-4]]:16}:")" - // CHECK: fix-it:{{.*}}:{[[@LINE-5]]:18-[[@LINE-5]]:18}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-6]]:31-[[@LINE-6]]:31}:")" - // CHECK: fix-it:{{.*}}:{[[@LINE-7]]:33-[[@LINE-7]]:33}:"static_cast<void>(" - // CHECK: fix-it:{{.*}}:{[[@LINE-8]]:46-[[@LINE-8]]:46}:")" + (void)T{}, 0; + static_cast<void>(T{}), 0; } +#endif // ifdef __cplusplus diff --git a/test/SemaCXX/warn-exit-time-destructors.cpp b/test/SemaCXX/warn-exit-time-destructors.cpp index 124576aa95b6d..17b3a9406369f 100644 --- a/test/SemaCXX/warn-exit-time-destructors.cpp +++ b/test/SemaCXX/warn-exit-time-destructors.cpp @@ -43,3 +43,8 @@ namespace test3 { }; E e; } + +namespace test4 { +struct A { ~A(); }; +[[clang::no_destroy]] A a; // no warning +} diff --git a/test/SemaCXX/warn-float-conversion.cpp b/test/SemaCXX/warn-float-conversion.cpp index a3d178622c7d7..7dec4844b062e 100644 --- a/test/SemaCXX/warn-float-conversion.cpp +++ b/test/SemaCXX/warn-float-conversion.cpp @@ -41,6 +41,32 @@ void Convert(float f, double d, long double ld) { l = ld; //expected-warning{{conversion}} } +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}} + + int y = x += 1.4f; //expected-warning{{conversion}} + + float z = 1.1f; + double w = -2.2; + + y += z + w; //expected-warning{{conversion}} +} + +# 1 "foo.h" 3 +// ^ the following text comes from a system header file. +#define SYSTEM_MACRO_FLOAT(x) do { (x) += 1.1; } while(0) +# 1 "warn-float-conversion.cpp" 1 +// ^ start of a new file. +void SystemMacro() { + float x = 0.0f; + SYSTEM_MACRO_FLOAT(x); +} + void Test() { int a1 = 10.0/2.0; //expected-warning{{conversion}} int a2 = 1.0/2.0; //expected-warning{{conversion}} diff --git a/test/SemaCXX/warn-loop-analysis.cpp b/test/SemaCXX/warn-loop-analysis.cpp index 2934003848a28..324dd386292ac 100644 --- a/test/SemaCXX/warn-loop-analysis.cpp +++ b/test/SemaCXX/warn-loop-analysis.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify -std=c++17 %s struct S { bool stop() { return false; } @@ -278,3 +278,24 @@ void test9() { // Don't warn when variable is defined by the loop condition. for (int i = 0; int x = f(i); ++i) {} } + +// Don't warn when decomposition variables are in the loop condition. +// TODO: BindingDecl's which make a copy should warn. +void test10() { + int arr[] = {1, 2, 3}; + for (auto[i, j, k] = arr;;) { } + for (auto[i, j, k] = arr; i < j; ++i, ++j) { } + + for (auto[i, j, k] = arr; i;) { } + for (auto[i, j, k] = arr; i < j;) { } + for (auto[i, j, k] = arr; i < j; ++arr[0]) { } + + int a = 1, b = 2; + for (auto[i, j, k] = arr; a < b;) { } // expected-warning{{variables 'a' and 'b' used in loop condition not modified in loop body}} + for (auto[i, j, k] = arr; a < b; ++a) { } + + for (auto [i, j, k] = arr; i < a;) { } + for (auto[i, j, k] = arr; i < a; ++a) { } + for (auto[i, j, k] = arr; i < a; ++i) { } + for (auto[i, j, k] = arr; i < a; ++arr[0]) { } +}; diff --git a/test/SemaCXX/warn-overloaded-virtual.cpp b/test/SemaCXX/warn-overloaded-virtual.cpp index 6204826192d7b..271416d04d55d 100644 --- a/test/SemaCXX/warn-overloaded-virtual.cpp +++ b/test/SemaCXX/warn-overloaded-virtual.cpp @@ -130,7 +130,7 @@ namespace { virtual int foo(int*) const; // expected-note@-1{{type mismatch at 1st parameter ('int *' vs 'int')}} virtual int foo(int) volatile; - // expected-note@-1{{different qualifiers (volatile vs const)}} + // expected-note@-1{{different qualifiers ('volatile' vs 'const')}} }; class B : public A { diff --git a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp index e69a81b77f70a..3312b5635f062 100644 --- a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp +++ b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wcall-to-pure-virtual-from-ctor-dtor struct A { A() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'A'}} ~A() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the destructor of 'A'}} diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp index b0dcd122a540d..a772af049ab41 100644 --- a/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s +// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s void foo(int param) { // expected-note 1+ {{previous declaration is here}} int var = 0; // expected-note 1+ {{previous declaration is here}} @@ -79,7 +80,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} int var = 1; // expected-warning {{declaration shadows a local variable}} }; auto f2 = [param] // expected-note {{variable 'param' is explicitly captured here}} - (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} } // Warn for variables defined in the capture list. @@ -135,7 +136,7 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}} auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}} #endif auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}} - (auto param) { ; }; // expected-warning {{declaration shadows a local variable}} + (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} } void avoidWarningWhenRedefining() { diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp index 3d09c786285ad..f4a904b7ed379 100644 --- a/test/SemaCXX/warn-shadow.cpp +++ b/test/SemaCXX/warn-shadow.cpp @@ -59,13 +59,13 @@ class A { // expected-warning-re@+1 4 {{constructor parameter 'f{{[0-4]}}' shadows the field 'f{{[0-9]}}' of 'A'}} A(int f1, int f2, int f3, int f4, double overload_dummy) {} - void test() { - char *field; // expected-warning {{declaration shadows a field of 'A'}} - char *data; // expected-warning {{declaration shadows a static data member of 'A'}} + void test() {
+ char *field; // expected-warning {{declaration shadows a field of 'A'}}
+ char *data; // expected-warning {{declaration shadows a static data member of 'A'}}
char *a1; // no warning - char *a2; // no warning - char *jj; // no warning - char *jjj; // no warning + char *a2; // no warning
+ char *jj; // no warning
+ char *jjj; // no warning
} void test2() { @@ -196,14 +196,14 @@ void avoidWarningWhenRedefining(int b) { // expected-note {{previous definition int k; // expected-note {{previous definition is here}} typedef int k; // expected-error {{redefinition of 'k'}} - using l=char; // no warning or error. - using l=char; // no warning or error. - typedef char l; // no warning or error. + using l=char; // no warning or error.
+ using l=char; // no warning or error.
+ typedef char l; // no warning or error.
typedef char n; // no warning or error. typedef char n; // no warning or error. - using n=char; // no warning or error. -} + using n=char; // no warning or error.
+}
} @@ -219,6 +219,49 @@ void f(int a) { struct A { void g(int a) {} A() { int a; } + };
+}
+}
+
+namespace PR34120 {
+struct A {
+ int B; // expected-note 2 {{declared here}}
+};
+
+class C : public A {
+ void D(int B) {} // expected-warning {{parameter 'B' shadows member inherited from type 'A'}}
+ void E() {
+ extern void f(int B); // Ok
+ }
+ void F(int B); // Ok, declaration; not definition.
+ void G(int B);
+};
+
+void C::G(int B) { // expected-warning {{parameter 'B' shadows member inherited from type 'A'}}
+}
+
+class Private {
+ int B;
+};
+class Derived : Private {
+ void D(int B) {} // Ok
+};
+
+struct Static {
+ static int B;
+};
+
+struct Derived2 : Static {
+ void D(int B) {}
+};
+}
+ +int PR24718; +enum class X { PR24718 }; // Ok, not shadowing + +struct PR24718_1; +struct PR24718_2 { + enum { + PR24718_1 // Does not shadow a type. }; -} -} +}; diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 51535be97d97e..f959beb6221e2 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -6,42 +6,7 @@ // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s -#define SCOPED_LOCKABLE __attribute__((scoped_lockable)) -#define GUARDED_BY(x) __attribute__((guarded_by(x))) -#define GUARDED_VAR __attribute__((guarded_var)) -#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x))) -#define PT_GUARDED_VAR __attribute__((pt_guarded_var)) -#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) -#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) - -#if USE_CAPABILITY -#define LOCKABLE __attribute__((capability("mutex"))) -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__))) -#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) -#else -#define LOCKABLE __attribute__((lockable)) -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) -#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) -#endif -#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) -#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) -#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) -#define LOCK_RETURNED(x) __attribute__((lock_returned(x))) -#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) -#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) - +#include "thread-safety-annotations.h" class LOCKABLE Mutex { public: @@ -1789,6 +1754,13 @@ struct TestTryLock { mu.Unlock(); } + void foo2_builtin_expect() { + if (__builtin_expect(!mu.TryLock(), false)) + return; + a = 2; + mu.Unlock(); + } + void foo3() { bool b = mu.TryLock(); if (b) { @@ -1797,6 +1769,14 @@ struct TestTryLock { } } + void foo3_builtin_expect() { + bool b = mu.TryLock(); + if (__builtin_expect(b, true)) { + a = 3; + mu.Unlock(); + } + } + void foo4() { bool b = mu.TryLock(); if (!b) return; @@ -1893,6 +1873,23 @@ struct TestTryLock { int i = a; mu.Unlock(); } + + // Test with conditional operator + void foo13() { + if (mu.TryLock() ? 1 : 0) + mu.Unlock(); + } + + void foo14() { + if (mu.TryLock() ? 0 : 1) + return; + mu.Unlock(); + } + + void foo15() { + if (mu.TryLock() ? 0 : 1) // expected-note{{mutex acquired here}} + mu.Unlock(); // expected-warning{{releasing mutex 'mu' that was not held}} + } // expected-warning{{mutex 'mu' is not held on every path through here}} }; // end TestTrylock } // end namespace TrylockTest @@ -2358,6 +2355,7 @@ Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); } void test() { Foo foo; Foo *fooArray; + Foo &(*fooFuncPtr)(); Bar bar; int a; int b; @@ -2394,6 +2392,10 @@ void test() { (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); (a > 0 ? fooArray[1] : fooArray[b]).a = 0; (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); + + fooFuncPtr().mu_.Lock(); + fooFuncPtr().a = 0; + fooFuncPtr().mu_.Unlock(); } @@ -2621,6 +2623,274 @@ void Foo::test5() { } // end namespace ReleasableScopedLock +namespace RelockableScopedLock { + +class SCOPED_LOCKABLE RelockableExclusiveMutexLock { +public: + RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu); + ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION(); + + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); +}; + +struct SharedTraits {}; +struct ExclusiveTraits {}; + +class SCOPED_LOCKABLE RelockableMutexLock { +public: + RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu); + RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu); + ~RelockableMutexLock() UNLOCK_FUNCTION(); + + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); + + void ReaderLock() SHARED_LOCK_FUNCTION(); + void ReaderUnlock() UNLOCK_FUNCTION(); + + void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(); + void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION(); +}; + +Mutex mu; +int x GUARDED_BY(mu); + +void print(int); + +void relock() { + RelockableExclusiveMutexLock scope(&mu); + x = 2; + scope.Unlock(); + + x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} + + scope.Lock(); + x = 4; +} + +void relockExclusive() { + RelockableMutexLock scope(&mu, SharedTraits{}); + print(x); + x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} + scope.ReaderUnlock(); + + print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} + + scope.Lock(); + print(x); + x = 4; + + scope.DemoteExclusive(); + print(x); + x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} +} + +void relockShared() { + RelockableMutexLock scope(&mu, ExclusiveTraits{}); + print(x); + x = 2; + scope.Unlock(); + + print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} + + scope.ReaderLock(); + print(x); + x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} + + scope.PromoteShared(); + print(x); + x = 5; +} + +void doubleUnlock() { + RelockableExclusiveMutexLock scope(&mu); + scope.Unlock(); + scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}} +} + +void doubleLock1() { + RelockableExclusiveMutexLock scope(&mu); + scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} +} + +void doubleLock2() { + RelockableExclusiveMutexLock scope(&mu); + scope.Unlock(); + scope.Lock(); + scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} +} + +void directUnlock() { + RelockableExclusiveMutexLock scope(&mu); + mu.Unlock(); + // Debatable that there is no warning. Currently we don't track in the scoped + // object whether it is active, but just check if the contained locks can be + // reacquired. Here they can, because mu has been unlocked manually. + scope.Lock(); +} + +void directRelock() { + RelockableExclusiveMutexLock scope(&mu); + scope.Unlock(); + mu.Lock(); + // Similarly debatable that there is no warning. + scope.Unlock(); +} + +// Doesn't make a lot of sense, just making sure there is no crash. +void destructLock() { + RelockableExclusiveMutexLock scope(&mu); + scope.~RelockableExclusiveMutexLock(); + scope.Lock(); // Should be UB, so we don't really care. +} + +class SCOPED_LOCKABLE MemberLock { +public: + MemberLock() EXCLUSIVE_LOCK_FUNCTION(mutex); + ~MemberLock() UNLOCK_FUNCTION(mutex); + void Lock() EXCLUSIVE_LOCK_FUNCTION(mutex); + Mutex mutex; +}; + +void relockShared2() { + MemberLock lock; + lock.Lock(); // expected-warning {{acquiring mutex 'lock.mutex' that is already held}} +} + +class SCOPED_LOCKABLE WeirdScope { +private: + Mutex *other; + +public: + WeirdScope(Mutex *mutex) EXCLUSIVE_LOCK_FUNCTION(mutex); + void unlock() EXCLUSIVE_UNLOCK_FUNCTION() EXCLUSIVE_UNLOCK_FUNCTION(other); + void lock() EXCLUSIVE_LOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(other); + ~WeirdScope() EXCLUSIVE_UNLOCK_FUNCTION(); + + void requireOther() EXCLUSIVE_LOCKS_REQUIRED(other); +}; + +void relockWeird() { + WeirdScope scope(&mu); + x = 1; + scope.unlock(); // expected-warning {{releasing mutex 'scope.other' that was not held}} + x = 2; // \ + // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} + scope.requireOther(); // \ + // expected-warning {{calling function 'requireOther' requires holding mutex 'scope.other' exclusively}} + scope.lock(); // expected-note {{mutex acquired here}} + x = 3; + scope.requireOther(); +} // expected-warning {{mutex 'scope.other' is still held at the end of function}} + +} // end namespace RelockableScopedLock + + +namespace ScopedUnlock { + +class SCOPED_LOCKABLE MutexUnlock { +public: + MutexUnlock(Mutex *mu) EXCLUSIVE_UNLOCK_FUNCTION(mu); + ~MutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION(); + + void Lock() EXCLUSIVE_UNLOCK_FUNCTION(); + void Unlock() EXCLUSIVE_LOCK_FUNCTION(); +}; + +class SCOPED_LOCKABLE ReaderMutexUnlock { +public: + ReaderMutexUnlock(Mutex *mu) SHARED_UNLOCK_FUNCTION(mu); + ~ReaderMutexUnlock() EXCLUSIVE_UNLOCK_FUNCTION(); + + void Lock() EXCLUSIVE_UNLOCK_FUNCTION(); + void Unlock() EXCLUSIVE_LOCK_FUNCTION(); +}; + +Mutex mu; +int x GUARDED_BY(mu); +bool c; +void print(int); + +void simple() EXCLUSIVE_LOCKS_REQUIRED(mu) { + x = 1; + MutexUnlock scope(&mu); + x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} +} + +void simpleShared() SHARED_LOCKS_REQUIRED(mu) { + print(x); + ReaderMutexUnlock scope(&mu); + print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} +} + +void innerUnlock() { + MutexLock outer(&mu); + if (x == 0) { + MutexUnlock inner(&mu); + x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} + } + x = 2; +} + +void innerUnlockShared() { + ReaderMutexLock outer(&mu); + if (x == 0) { + ReaderMutexUnlock inner(&mu); + print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} + } + print(x); +} + +void manual() EXCLUSIVE_LOCKS_REQUIRED(mu) { + MutexUnlock scope(&mu); + scope.Lock(); + x = 2; + scope.Unlock(); + x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} +} + +void join() EXCLUSIVE_LOCKS_REQUIRED(mu) { + MutexUnlock scope(&mu); + if (c) { + scope.Lock(); // expected-note{{mutex acquired here}} + } + // expected-warning@+1{{mutex 'mu' is not held on every path through here}} + scope.Lock(); +} + +void doubleLock() EXCLUSIVE_LOCKS_REQUIRED(mu) { + MutexUnlock scope(&mu); + scope.Lock(); + scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} +} + +void doubleUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) { + MutexUnlock scope(&mu); + scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}} +} + +class SCOPED_LOCKABLE MutexLockUnlock { +public: + MutexLockUnlock(Mutex *mu1, Mutex *mu2) EXCLUSIVE_UNLOCK_FUNCTION(mu1) EXCLUSIVE_LOCK_FUNCTION(mu2); + ~MutexLockUnlock() EXCLUSIVE_UNLOCK_FUNCTION(); + + void Release() EXCLUSIVE_UNLOCK_FUNCTION(); + void Acquire() EXCLUSIVE_LOCK_FUNCTION(); +}; + +Mutex other; +void fn() EXCLUSIVE_LOCKS_REQUIRED(other); + +void lockUnlock() EXCLUSIVE_LOCKS_REQUIRED(mu) { + MutexLockUnlock scope(&mu, &other); + fn(); + x = 1; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} +} + +} // end namespace ScopedUnlock + + namespace TrylockFunctionTest { class Foo { @@ -4078,6 +4348,14 @@ public: mu_.Unlock(); } + void unlockExclusive() EXCLUSIVE_UNLOCK_FUNCTION(mu_) { + mu_.Unlock(); + } + + void unlockShared() SHARED_UNLOCK_FUNCTION(mu_) { + mu_.ReaderUnlock(); + } + // Check failure to lock. void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} mu2_.Lock(); @@ -4840,6 +5118,8 @@ public: void operator+(const Foo& f); void operator[](const Foo& g); + + void operator()(); }; template<class T> @@ -4857,8 +5137,23 @@ void destroy(Foo&& f); void operator/(const Foo& f, const Foo& g); void operator*(const Foo& f, const Foo& g); +// Test constructors. +struct FooRead { + FooRead(const Foo &); +}; +struct FooWrite { + FooWrite(Foo &); +}; +// Test variadic functions +template<typename... T> +void copyVariadic(T...) {} +template<typename... T> +void writeVariadic(T&...) {} +template<typename... T> +void readVariadic(const T&...) {} +void copyVariadicC(int, ...); class Bar { public: @@ -4890,6 +5185,14 @@ public: read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} + copyVariadic(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} + readVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} + writeVariadic(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} + copyVariadicC(1, foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} + + FooRead reader(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} + FooWrite writer(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} + mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} @@ -4908,6 +5211,7 @@ public: // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}} foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \ // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}} + foo(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}} copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}} @@ -5331,3 +5635,106 @@ namespace ReturnScopedLockable { return ptr->f(); } } + +namespace PR38640 { +void f() { + // Self-referencing assignment previously caused an infinite loop when thread + // safety analysis was enabled. + int &i = i; // expected-warning {{reference 'i' is not yet bound to a value when used within its own initialization}} +} +} + +namespace Derived_Smart_Pointer { +template <class T> +class SmartPtr_Derived : public SmartPtr<T> {}; + +class Foo { +public: + SmartPtr_Derived<Mutex> mu_; + int a GUARDED_BY(mu_); + int b GUARDED_BY(mu_.get()); + int c GUARDED_BY(*mu_); + + void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_); + void Unlock() UNLOCK_FUNCTION(mu_); + + void test0() { + a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}} + b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}} + c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}} + } + + void test1() { + Lock(); + a = 1; + b = 1; + c = 1; + Unlock(); + } +}; + +class Bar { + SmartPtr_Derived<Foo> foo; + + void test0() { + foo->a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}} + (*foo).b = 1; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}} + foo.get()->c = 1; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}} + } + + void test1() { + foo->Lock(); + foo->a = 1; + foo->Unlock(); + + foo->mu_->Lock(); + foo->b = 1; + foo->mu_->Unlock(); + + MutexLock lock(foo->mu_.get()); + foo->c = 1; + } +}; + +class PointerGuard { + Mutex mu1; + Mutex mu2; + SmartPtr_Derived<int> i GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + + void test0() { + i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} + *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} \ + // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}} + + } + + void test1() { + mu1.Lock(); + + i.get(); + *i = 2; // expected-warning {{reading the value pointed to by 'i' requires holding mutex 'mu2'}} + + mu1.Unlock(); + } + + void test2() { + mu2.Lock(); + + i.get(); // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} + *i = 2; // expected-warning {{reading variable 'i' requires holding mutex 'mu1'}} + + mu2.Unlock(); + } + + void test3() { + mu1.Lock(); + mu2.Lock(); + + i.get(); + *i = 2; + + mu2.Unlock(); + mu1.Unlock(); + } +}; +} diff --git a/test/SemaCXX/warn-thread-safety-negative.cpp b/test/SemaCXX/warn-thread-safety-negative.cpp index f831010293b61..9a495fa6cff9a 100644 --- a/test/SemaCXX/warn-thread-safety-negative.cpp +++ b/test/SemaCXX/warn-thread-safety-negative.cpp @@ -1,40 +1,18 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s -#define LOCKABLE __attribute__ ((lockable)) -#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) -#define GUARDED_BY(x) __attribute__ ((guarded_by(x))) -#define GUARDED_VAR __attribute__ ((guarded_var)) -#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) -#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) -#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) -#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__))) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) -#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) -#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) -#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) -#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) \ - __attribute__ ((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) \ - __attribute__ ((shared_locks_required(__VA_ARGS__))) -#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) - - -class __attribute__((lockable)) Mutex { +#include "thread-safety-annotations.h" + +class LOCKABLE Mutex { public: - void Lock() __attribute__((exclusive_lock_function)); - void ReaderLock() __attribute__((shared_lock_function)); - void Unlock() __attribute__((unlock_function)); - bool TryLock() __attribute__((exclusive_trylock_function(true))); - bool ReaderTryLock() __attribute__((shared_trylock_function(true))); - void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void ReaderLock() SHARED_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); + bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); + bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); // for negative capabilities const Mutex& operator!() const { return *this; } diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index ac357e8dae375..198d02e1f0768 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -572,11 +572,11 @@ UnlockableMu ab_var_arg_bad_5 ACQUIRED_BEFORE(mu_ab); // \ // takes zero or more arguments, all locks (vars/fields) -void elf_function() EXCLUSIVE_LOCK_FUNCTION(); +void elf_function() EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} void elf_function_args() EXCLUSIVE_LOCK_FUNCTION(mu1, mu2); -int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); +int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} int elf_testfn(int y) { int x EXCLUSIVE_LOCK_FUNCTION() = y; // \ @@ -591,7 +591,8 @@ class ElfFoo { private: int test_field EXCLUSIVE_LOCK_FUNCTION(); // \ // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} - void test_method() EXCLUSIVE_LOCK_FUNCTION(); + void test_method() EXCLUSIVE_LOCK_FUNCTION(); // \ + // expected-warning {{'exclusive_lock_function' attribute without capability arguments refers to 'this', but 'ElfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} }; class EXCLUSIVE_LOCK_FUNCTION() ElfTestClass { // \ @@ -644,11 +645,11 @@ int elf_function_bad_7() EXCLUSIVE_LOCK_FUNCTION(0); // \ // takes zero or more arguments, all locks (vars/fields) -void slf_function() SHARED_LOCK_FUNCTION(); +void slf_function() SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} void slf_function_args() SHARED_LOCK_FUNCTION(mu1, mu2); -int slf_testfn(int y) SHARED_LOCK_FUNCTION(); +int slf_testfn(int y) SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} int slf_testfn(int y) { int x SHARED_LOCK_FUNCTION() = y; // \ @@ -666,7 +667,8 @@ class SlfFoo { private: int test_field SHARED_LOCK_FUNCTION(); // \ // expected-warning {{'shared_lock_function' attribute only applies to functions}} - void test_method() SHARED_LOCK_FUNCTION(); + void test_method() SHARED_LOCK_FUNCTION(); // \ + // expected-warning {{'shared_lock_function' attribute without capability arguments refers to 'this', but 'SlfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} }; class SHARED_LOCK_FUNCTION() SlfTestClass { // \ @@ -717,14 +719,16 @@ int slf_function_bad_7() SHARED_LOCK_FUNCTION(0); // \ // takes a mandatory boolean or integer argument specifying the retval // plus an optional list of locks (vars/fields) -void etf_function() __attribute__((exclusive_trylock_function)); // \ +void etf_function() __attribute__((exclusive_trylock_function)); // \ // expected-error {{'exclusive_trylock_function' attribute takes at least 1 argument}} void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2); -void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); +void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ + // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} -int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); +int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ + // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} int etf_testfn(int y) { int x EXCLUSIVE_TRYLOCK_FUNCTION(1) = y; // \ @@ -739,7 +743,8 @@ class EtfFoo { private: int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} - void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); + void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ + // expected-warning {{'exclusive_trylock_function' attribute without capability arguments refers to 'this', but 'EtfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} }; class EXCLUSIVE_TRYLOCK_FUNCTION(1) EtfTestClass { // \ @@ -760,7 +765,8 @@ int etf_function_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, &mu1); int etf_function_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, muRef); int etf_function_7() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); int etf_functetfn_8() EXCLUSIVE_TRYLOCK_FUNCTION(1, muPointer); -int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); +int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); // \ + // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} // illegal attribute arguments @@ -795,9 +801,11 @@ void stf_function() __attribute__((shared_trylock_function)); // \ void stf_function_args() SHARED_TRYLOCK_FUNCTION(1, mu2); -void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); +void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); // \ + // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} -int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); +int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); // \ + // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} int stf_testfn(int y) { int x SHARED_TRYLOCK_FUNCTION(1) = y; // \ @@ -816,7 +824,8 @@ class StfFoo { private: int test_field SHARED_TRYLOCK_FUNCTION(1); // \ // expected-warning {{'shared_trylock_function' attribute only applies to functions}} - void test_method() SHARED_TRYLOCK_FUNCTION(1); + void test_method() SHARED_TRYLOCK_FUNCTION(1); // \ + // expected-warning {{'shared_trylock_function' attribute without capability arguments refers to 'this', but 'StfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} }; class SHARED_TRYLOCK_FUNCTION(1) StfTestClass { // \ @@ -834,7 +843,8 @@ int stf_function_5() SHARED_TRYLOCK_FUNCTION(1, &mu1); int stf_function_6() SHARED_TRYLOCK_FUNCTION(1, muRef); int stf_function_7() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); int stf_function_8() SHARED_TRYLOCK_FUNCTION(1, muPointer); -int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); +int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); // \ + // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} // illegal attribute arguments @@ -863,11 +873,14 @@ int stf_function_bad_6() SHARED_TRYLOCK_FUNCTION(1, umu); // \ // takes zero or more arguments, all locks (vars/fields) -void uf_function() UNLOCK_FUNCTION(); +void uf_function() UNLOCK_FUNCTION(); // \ + // expected-warning {{'unlock_function' attribute without capability arguments can only be applied to non-static methods of a class}} + void uf_function_args() UNLOCK_FUNCTION(mu1, mu2); -int uf_testfn(int y) UNLOCK_FUNCTION(); +int uf_testfn(int y) UNLOCK_FUNCTION(); //\ + // expected-warning {{'unlock_function' attribute without capability arguments can only be applied to non-static methods of a class}} int uf_testfn(int y) { int x UNLOCK_FUNCTION() = y; // \ @@ -882,7 +895,8 @@ class UfFoo { private: int test_field UNLOCK_FUNCTION(); // \ // expected-warning {{'unlock_function' attribute only applies to functions}} - void test_method() UNLOCK_FUNCTION(); + void test_method() UNLOCK_FUNCTION(); // \ + // expected-warning {{'unlock_function' attribute without capability arguments refers to 'this', but 'UfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} }; class NO_THREAD_SAFETY_ANALYSIS UfTestClass { // \ @@ -1250,6 +1264,36 @@ struct Foomgoper { } }; +template <typename Mutex> +struct SCOPED_LOCKABLE SLTemplateClass { + ~SLTemplateClass() UNLOCK_FUNCTION(); +}; + +template <typename Mutex> +struct NonSLTemplateClass { + ~NonSLTemplateClass() UNLOCK_FUNCTION(); // \ + // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'NonSLTemplateClass' isn't annotated with 'capability' or 'scoped_lockable' attribute}} +}; + +template <> +struct SLTemplateClass<int> {}; + +template <typename Mutex> +struct SLTemplateDerived : public SLTemplateClass<Mutex> { + ~SLTemplateDerived() UNLOCK_FUNCTION(); +}; + +// FIXME: warn on template instantiation. +template struct SLTemplateDerived<int>; + +struct SLDerived1 : public SLTemplateClass<double> { + ~SLDerived1() UNLOCK_FUNCTION(); +}; + +struct SLDerived2 : public SLTemplateClass<int> { + ~SLDerived2() UNLOCK_FUNCTION(); // \ + // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'SLDerived2' isn't annotated with 'capability' or 'scoped_lockable' attribute}} +}; //----------------------------------------------------- // Parsing of member variables and function parameters @@ -1525,4 +1569,4 @@ namespace CRASH_POST_R301735 { Mutex mu_; }; } -#endif
\ No newline at end of file +#endif diff --git a/test/SemaCXX/warn-thread-safety-verbose.cpp b/test/SemaCXX/warn-thread-safety-verbose.cpp index 4e19f30bf2c3e..2f892cd1e1754 100644 --- a/test/SemaCXX/warn-thread-safety-verbose.cpp +++ b/test/SemaCXX/warn-thread-safety-verbose.cpp @@ -1,37 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wthread-safety-verbose -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s -#define LOCKABLE __attribute__ ((lockable)) -#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) -#define GUARDED_BY(x) __attribute__ ((guarded_by(x))) -#define GUARDED_VAR __attribute__ ((guarded_var)) -#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) -#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) -#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) -#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__))) -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) -#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) -#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) -#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) -#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) -#define EXCLUSIVE_LOCKS_REQUIRED(...) \ - __attribute__ ((exclusive_locks_required(__VA_ARGS__))) -#define SHARED_LOCKS_REQUIRED(...) \ - __attribute__ ((shared_locks_required(__VA_ARGS__))) -#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) +#include "thread-safety-annotations.h" - -class __attribute__((lockable)) Mutex { +class LOCKABLE Mutex { public: - void Lock() __attribute__((exclusive_lock_function)); - void ReaderLock() __attribute__((shared_lock_function)); - void Unlock() __attribute__((unlock_function)); - bool TryLock() __attribute__((exclusive_trylock_function(true))); - bool ReaderTryLock() __attribute__((shared_trylock_function(true))); - void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void ReaderLock() SHARED_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); + bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); + bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); // for negative capabilities const Mutex& operator!() const { return *this; } diff --git a/test/SemaCXX/warn-unsequenced-cxx17.cpp b/test/SemaCXX/warn-unsequenced-cxx17.cpp new file mode 100644 index 0000000000000..3c221fb8d6560 --- /dev/null +++ b/test/SemaCXX/warn-unsequenced-cxx17.cpp @@ -0,0 +1,8 @@ +// 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 9e8a5b46c218a..6d4468cabfe56 100644 --- a/test/SemaCXX/warn-unsequenced.cpp +++ b/test/SemaCXX/warn-unsequenced.cpp @@ -81,6 +81,7 @@ void test() { 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'}} A *q = &agg1; (q = &agg2)->y = q->x; // expected-warning {{unsequenced modification and access to 'q'}} diff --git a/test/SemaCXX/warn-unused-result.cpp b/test/SemaCXX/warn-unused-result.cpp index 88f5ab1e85c06..f1de4618a741a 100644 --- a/test/SemaCXX/warn-unused-result.cpp +++ b/test/SemaCXX/warn-unused-result.cpp @@ -33,6 +33,36 @@ void test() { const S &s4 = g1(); } +void testSubstmts(int i) { + switch (i) { + case 0: + f(); // expected-warning {{ignoring return value}} + default: + f(); // expected-warning {{ignoring return value}} + } + + if (i) + f(); // expected-warning {{ignoring return value}} + else + f(); // expected-warning {{ignoring return value}} + + while (i) + f(); // expected-warning {{ignoring return value}} + + do + f(); // expected-warning {{ignoring return value}} + while (i); + + for (f(); // expected-warning {{ignoring return value}} + ; + f() // expected-warning {{ignoring return value}} + ) + f(); // expected-warning {{ignoring return value}} + + f(), // expected-warning {{ignoring return value}} + (void)f(); +} + struct X { int foo() __attribute__((warn_unused_result)); }; @@ -206,3 +236,13 @@ void f() { (void)++p; } } // namespace + +namespace PR39837 { +[[clang::warn_unused_result]] int f(int); + +void g() { + int a[2]; + for (int b : a) + f(b); // expected-warning {{ignoring return value}} +} +} // namespace PR39837 |