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