aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/MicrosoftCompatibility.cpp20
-rw-r--r--test/SemaCXX/PR38913.cpp12
-rw-r--r--test/SemaCXX/addr-of-overloaded-function.cpp14
-rw-r--r--test/SemaCXX/aggregate-initialization.cpp48
-rw-r--r--test/SemaCXX/alias-template.cpp16
-rw-r--r--test/SemaCXX/align-x86-abi7.cpp25
-rw-r--r--test/SemaCXX/align-x86.cpp62
-rw-r--r--test/SemaCXX/alignof.cpp19
-rw-r--r--test/SemaCXX/array-bounds.cpp12
-rw-r--r--test/SemaCXX/attr-cpuspecific.cpp3
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp36
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp45
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp69
-rw-r--r--test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp43
-rw-r--r--test/SemaCXX/attr-gnu.cpp21
-rw-r--r--test/SemaCXX/attr-on-explicit-template-instantiation.cpp25
-rw-r--r--test/SemaCXX/attr-optnone.cpp8
-rw-r--r--test/SemaCXX/attr-print.cpp4
-rw-r--r--test/SemaCXX/attr-reinitializes.cpp15
-rw-r--r--test/SemaCXX/attr-speculative-load-hardening.cpp34
-rw-r--r--test/SemaCXX/auto-pragma.cpp12
-rw-r--r--test/SemaCXX/builtins.cpp92
-rw-r--r--test/SemaCXX/calling-conv-compat.cpp43
-rw-r--r--test/SemaCXX/char8_t.cpp10
-rw-r--r--test/SemaCXX/compound-literal.cpp14
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp6
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp41
-rw-r--r--test/SemaCXX/constant-expression-cxx2a.cpp7
-rw-r--r--test/SemaCXX/constexpr-string.cpp252
-rw-r--r--test/SemaCXX/constructor.cpp11
-rw-r--r--test/SemaCXX/coreturn-eh.cpp45
-rw-r--r--test/SemaCXX/coroutine-rvo.cpp69
-rw-r--r--test/SemaCXX/coroutine-source-location-crash.cpp33
-rw-r--r--test/SemaCXX/cxx03-aligned-allocation-unscoped-enum.cpp21
-rw-r--r--test/SemaCXX/cxx0x-defaulted-functions.cpp8
-rw-r--r--test/SemaCXX/cxx0x-deleted-default-ctor.cpp6
-rw-r--r--test/SemaCXX/cxx0x-initializer-scalars.cpp23
-rw-r--r--test/SemaCXX/cxx11-compat.cpp (renamed from test/SemaCXX/cxx0x-compat.cpp)26
-rw-r--r--test/SemaCXX/cxx14-compat.cpp34
-rw-r--r--test/SemaCXX/cxx17-compat.cpp38
-rw-r--r--test/SemaCXX/cxx1y-deduced-return-type.cpp68
-rw-r--r--test/SemaCXX/cxx1y-init-captures.cpp8
-rw-r--r--test/SemaCXX/cxx1z-class-template-argument-deduction.cpp7
-rw-r--r--test/SemaCXX/cxx1z-init-statement.cpp8
-rw-r--r--test/SemaCXX/cxx2a-compat.cpp39
-rw-r--r--test/SemaCXX/cxx2a-initializer-aggregates.cpp23
-rw-r--r--test/SemaCXX/cxx2a-lambda-default-ctor-assign.cpp37
-rw-r--r--test/SemaCXX/cxx98-compat.cpp3
-rw-r--r--test/SemaCXX/delete-non-virtual-dtor.cpp30
-rw-r--r--test/SemaCXX/designated-initializers.cpp1
-rw-r--r--test/SemaCXX/dr1301.cpp6
-rw-r--r--test/SemaCXX/enable_if.cpp3
-rw-r--r--test/SemaCXX/enum.cpp2
-rw-r--r--test/SemaCXX/exception-spec.cpp47
-rw-r--r--test/SemaCXX/for-range-dereference.cpp6
-rw-r--r--test/SemaCXX/for-range-examples.cpp2
-rw-r--r--test/SemaCXX/friend-template-redecl.cpp20
-rw-r--r--test/SemaCXX/friend.cpp53
-rw-r--r--test/SemaCXX/friend2.cpp89
-rw-r--r--test/SemaCXX/implicit-exception-spec.cpp22
-rw-r--r--test/SemaCXX/lambda-invalid-capture.cpp18
-rw-r--r--test/SemaCXX/member-init.cpp20
-rw-r--r--test/SemaCXX/microsoft-dtor-lookup-cxx11.cpp4
-rw-r--r--test/SemaCXX/microsoft-varargs.cpp1
-rw-r--r--test/SemaCXX/ms-uuid.cpp8
-rw-r--r--test/SemaCXX/multistep-explicit-cast.cpp155
-rw-r--r--test/SemaCXX/no_destroy.cpp46
-rw-r--r--test/SemaCXX/rdar42746401.cpp7
-rw-r--r--test/SemaCXX/sourceranges.cpp139
-rw-r--r--test/SemaCXX/static-assert-cxx17.cpp104
-rw-r--r--test/SemaCXX/static-assert.cpp124
-rw-r--r--test/SemaCXX/string-plus-int.cpp23
-rw-r--r--test/SemaCXX/struct-class-redecl.cpp31
-rw-r--r--test/SemaCXX/subst-restrict.cpp18
-rw-r--r--test/SemaCXX/switch-implicit-fallthrough.cpp15
-rw-r--r--test/SemaCXX/template-implicit-vars.cpp14
-rw-r--r--test/SemaCXX/thread-safety-annotations.h42
-rw-r--r--test/SemaCXX/unavailable_aligned_allocation.cpp77
-rw-r--r--test/SemaCXX/uninitialized.cpp6
-rw-r--r--test/SemaCXX/vector.cpp8
-rw-r--r--test/SemaCXX/warn-comma-operator.cpp245
-rw-r--r--test/SemaCXX/warn-exit-time-destructors.cpp5
-rw-r--r--test/SemaCXX/warn-float-conversion.cpp26
-rw-r--r--test/SemaCXX/warn-loop-analysis.cpp23
-rw-r--r--test/SemaCXX/warn-overloaded-virtual.cpp2
-rw-r--r--test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp2
-rw-r--r--test/SemaCXX/warn-shadow-in-lambdas.cpp5
-rw-r--r--test/SemaCXX/warn-shadow.cpp69
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp479
-rw-r--r--test/SemaCXX/warn-thread-safety-negative.cpp42
-rw-r--r--test/SemaCXX/warn-thread-safety-parsing.cpp82
-rw-r--r--test/SemaCXX/warn-thread-safety-verbose.cpp40
-rw-r--r--test/SemaCXX/warn-unsequenced-cxx17.cpp8
-rw-r--r--test/SemaCXX/warn-unsequenced.cpp1
-rw-r--r--test/SemaCXX/warn-unused-result.cpp40
95 files changed, 2983 insertions, 742 deletions
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp
index 203a81011142..727e67528fa0 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 000000000000..698de8c84411
--- /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 cca847b4d2c3..6b6734bae17d 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 0dfb61333ec2..bb03c6fb5cf1 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 b6256103ef8d..0a92b9dd9639 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 000000000000..3088a13f7857
--- /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 000000000000..0c97fc28fe5f
--- /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 e3690ea926a2..f2854024da1a 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 a97f8e312a05..6ebff8c99206 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 a881b6c4e2ba..7ec8c6cd0ce2 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 000000000000..24e24221939f
--- /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 000000000000..379ab0a3eb00
--- /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 000000000000..4cb02252ba35
--- /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 000000000000..da861ab97235
--- /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 a553f0d21000..9eb42342df31 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 000000000000..ddb9c8e2e4a5
--- /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 58776caf7ae6..c8e85eec3711 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 960050bc7106..d7ef42306bd3 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 000000000000..129d359b8b74
--- /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 000000000000..bba3b6921e8d
--- /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 1cd0781fe9a7..000000000000
--- 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 f26931b55bdb..fbe2c457dad9 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 4c4cc15f165a..a268d9da07ee 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 5eb3d7062d2c..f60a66dbe84d 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 be9ebee00c2f..353be2cf48e4 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 a64207583dd5..578a057104a3 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 00df2e5c77a4..3c57ac573f2c 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 18c4a726fd00..bb2a4a07dd8f 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 1145a2081cba..c348c0ff747d 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 105605c6e37b..33ea49663491 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 000000000000..79065736c0a4
--- /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 000000000000..8521b8506fd0
--- /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 04fb1d45c524..000000000000
--- 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 000000000000..7237fbf9db7f
--- /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 f623dc765f88..6346e1c23538 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 b9af67948bfc..80efd810f098 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 90b11f3a9e23..a13aa238de66 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 b9ccadd85c2d..07cd6b1fcf93 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 000000000000..d70f477cd09a
--- /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 3b814340c6da..eee9c239d188 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 13ff751acae4..fafc6ead73c4 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 4b82452ed592..16cffb2a914b 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 cbf7c2eee51c..c310c651408d 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 d37acd08ce77..eea2589ab7c6 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 000000000000..d51f1e6aab13
--- /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 000000000000..9c438d399b34
--- /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 000000000000..e555f16ecc1e
--- /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 f814a06f13be..885ab110ab1f 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 000000000000..b64eca3527f3
--- /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 e5b5f3c9cce2..04002c0b6c11 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 ec0db74554a8..b7dc91d56330 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 93014f50d508..ba520b047a32 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 cfe5760112f6..16ebebe31b6d 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 f301a63503dd..6ad19aab397b 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 7377199024e5..de4958c31bce 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 477789b56c14..5424b7a8ee79 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 000000000000..3e05964fb288
--- /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 1f64ba609b16..822b1de39a1e 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 8eacdeb19c62..6d3b545904e4 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 c21f773e94c6..19d645d6d3d1 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 000000000000..32349704caa2
--- /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 8a13eca2f177..2c4659afa3e7 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 5a399aa7eac2..000492e0edf1 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 5b0f90eb5ca0..311ce4a54f1f 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 624ac0541db4..c177570682f6 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 58466791354c..000000000000
--- 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 000000000000..7afbf9998253
--- /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 000000000000..ff9dff456ce4
--- /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 58772a063915..000000000000
--- 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 000000000000..fe02f8f29965
--- /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 846303807a02..a21cc874b566 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 fe9c71949698..448fb49fb49f 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 7375319186a1..622d5a0b652a 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 000000000000..aab6872d8de8
--- /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 9540b1ff2880..6ccac122cff7 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 25d35fbdb84f..000000000000
--- 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 000000000000..7755a1b328e7
--- /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 2000e0b6a319..2f0f8fe7a4b5 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 f620e1014c34..331a948eb6f1 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 56a8a6db5b68..a6a4ceb0e535 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 3192f688f1ba..0ed127b943f3 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 124576aa95b6..17b3a9406369 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 a3d178622c7d..7dec4844b062 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 2934003848a2..324dd386292a 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 6204826192d7..271416d04d55 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 e69a81b77f70..3312b5635f06 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 b0dcd122a540..a772af049ab4 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 3d09c786285a..f4a904b7ed37 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 51535be97d97..f959beb6221e 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 f831010293b6..9a495fa6cff9 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 ac357e8dae37..198d02e1f076 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 4e19f30bf2c3..2f892cd1e175 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 000000000000..3c221fb8d656
--- /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 9e8a5b46c218..6d4468cabfe5 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 88f5ab1e85c0..f1de4618a741 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