diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /test/SemaCXX | |
parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) | |
download | src-bab175ec4b075c8076ba14c762900392533f6ee4.tar.gz src-bab175ec4b075c8076ba14c762900392533f6ee4.zip |
Vendor import of clang trunk r290819:vendor/clang/clang-trunk-r290819
Notes
Notes:
svn path=/vendor/clang/dist/; revision=311118
svn path=/vendor/clang/clang-trunk-r290819/; revision=311119; tag=vendor/clang/clang-trunk-r290819
Diffstat (limited to 'test/SemaCXX')
99 files changed, 3013 insertions, 245 deletions
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp index fe8e8f77accb..26cd7825ee87 100644 --- a/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -99,23 +99,39 @@ int jump_over_indirect_goto() { namespace PR11826 { struct pair { pair(int v) { } +#if _MSC_VER >= 1900 + void operator=(pair&& rhs) { } // expected-note {{copy constructor is implicitly deleted because 'pair' has a user-declared move assignment operator}} +#else void operator=(pair&& rhs) { } +#endif }; void f() { pair p0(3); +#if _MSC_VER >= 1900 + pair p = p0; // expected-error {{call to implicitly-deleted copy constructor of 'PR11826::pair'}} +#else pair p = p0; +#endif } } namespace PR11826_for_symmetry { struct pair { pair(int v) { } +#if _MSC_VER >= 1900 + pair(pair&& rhs) { } // expected-note {{copy assignment operator is implicitly deleted because 'pair' has a user-declared move constructor}} +#else pair(pair&& rhs) { } +#endif }; void f() { pair p0(3); pair p(4); +#if _MSC_VER >= 1900 + p = p0; // expected-error {{object of type 'PR11826_for_symmetry::pair' cannot be assigned because its copy assignment operator is implicitly deleted}} +#else p = p0; +#endif } } @@ -242,3 +258,14 @@ namespace IntToNullPtrConv { template<int N> int *get_n() { return N; } // expected-warning {{expression which evaluates to zero treated as a null pointer constant}} int *g_nullptr = get_n<0>(); // expected-note {{in instantiation of function template specialization}} } + +namespace signed_hex_i64 { +void f(long long); +void f(int); +void g() { + // This is an ambiguous call in standard C++. + // This calls f(long long) in Microsoft mode because LL is always signed. + f(0xffffffffffffffffLL); + f(0xffffffffffffffffi64); +} +} diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index e10deadf7c7f..e12dea1fb620 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -158,19 +158,16 @@ void m1() { } - - - -void f(long long); -void f(int); - -int main() -{ - // This is an ambiguous call in standard C++. - // This calls f(long long) in Microsoft mode because LL is always signed. - f(0xffffffffffffffffLL); +namespace signed_hex_i64 { +void f(long long); // expected-note {{candidate function}} +void f(int); // expected-note {{candidate function}} +void g() { + // This used to be controlled by -fms-extensions, but it is now under + // -fms-compatibility. + f(0xffffffffffffffffLL); // expected-error {{call to 'f' is ambiguous}} f(0xffffffffffffffffi64); } +} // Enumeration types with a fixed underlying type. const int seventeen = 17; diff --git a/test/SemaCXX/PR25848.cpp b/test/SemaCXX/PR25848.cpp new file mode 100644 index 000000000000..a22ac6650a06 --- /dev/null +++ b/test/SemaCXX/PR25848.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A; + +inline int g(); // expected-warning{{inline function 'g' is not defined}} + +template<int M> +struct R { + friend int g() { + return M; + } +}; + +void m() { + g(); // expected-note{{used here}} +} diff --git a/test/SemaCXX/PR29152.cpp b/test/SemaCXX/PR29152.cpp new file mode 100644 index 000000000000..63c9c9bed545 --- /dev/null +++ b/test/SemaCXX/PR29152.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunreachable-code -verify %s + +static const bool False = false; + +struct A { + ~A(); + operator bool(); +}; +void Bar(); + +void Foo() { + if (False && A()) { + Bar(); // expected-no-diagnostics + } +} diff --git a/test/SemaCXX/PR8755.cpp b/test/SemaCXX/PR8755.cpp index 07778ddfc900..6818f3f0a822 100644 --- a/test/SemaCXX/PR8755.cpp +++ b/test/SemaCXX/PR8755.cpp @@ -7,7 +7,7 @@ struct A { template <typename T> void f() { - class A <T> ::iterator foo; // expected-error{{elaborated type refers to a typedef}} + class A <T> ::iterator foo; // expected-error{{typedef 'iterator' cannot be referenced with a class specifier}} } void g() { diff --git a/test/SemaCXX/address-packed-member-memops.cpp b/test/SemaCXX/address-packed-member-memops.cpp new file mode 100644 index 000000000000..6614626ae65c --- /dev/null +++ b/test/SemaCXX/address-packed-member-memops.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +struct B { + int x, y, z, w; +} b; + +struct __attribute__((packed)) A { + struct B b; +} a; + +typedef __typeof__(sizeof(int)) size_t; + +extern "C" { +void *memcpy(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); +} + +int x; + +void foo() { + memcpy(&a.b, &b, sizeof(b)); + memmove(&a.b, &b, sizeof(b)); + memset(&a.b, 0, sizeof(b)); + x = memcmp(&a.b, &b, sizeof(b)); +} diff --git a/test/SemaCXX/address-packed.cpp b/test/SemaCXX/address-packed.cpp new file mode 100644 index 000000000000..308c4858cd50 --- /dev/null +++ b/test/SemaCXX/address-packed.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +extern void f1(int *); +extern void f2(char *); + +struct __attribute__((packed)) Arguable { + int x; + char c; + static void foo(); +}; + +extern void f3(void()); + +namespace Foo { +struct __attribute__((packed)) Arguable { + char c; + int x; + static void foo(); +}; +} + +struct Arguable *get_arguable(); + +void f4(int &); + +void to_void(void *); + +template <typename... T> +void sink(T...); + +void g0() { + { + Foo::Arguable arguable; + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Foo::Arguable'}} + f2(&arguable.c); // no-warning + f3(&arguable.foo); // no-warning + + to_void(&arguable.x); // no-warning + void *p1 = &arguable.x; // no-warning + void *p2 = static_cast<void *>(&arguable.x); // no-warning + void *p3 = reinterpret_cast<void *>(&arguable.x); // no-warning + void *p4 = (void *)&arguable.x; // no-warning + sink(p1, p2, p3, p4); + } + { + Arguable arguable1; + Arguable &arguable(arguable1); + f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} + f2(&arguable.c); // no-warning + f3(&arguable.foo); // no-warning + } + { + Arguable *arguable1; + Arguable *&arguable(arguable1); + f1(&arguable->x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}} + f2(&arguable->c); // no-warning + f3(&arguable->foo); // no-warning + } +} + +struct __attribute__((packed)) A { + int x; + char c; + + int *f0() { + return &this->x; // expected-warning {{packed member 'x' of class or structure 'A'}} + } + + int *g0() { + return &x; // expected-warning {{packed member 'x' of class or structure 'A'}} + } + + char *h0() { + return &c; // no-warning + } +}; + +struct B : A { + int *f1() { + return &this->x; // expected-warning {{packed member 'x' of class or structure 'A'}} + } + + int *g1() { + return &x; // expected-warning {{packed member 'x' of class or structure 'A'}} + } + + char *h1() { + return &c; // no-warning + } +}; + +template <typename Ty> +class __attribute__((packed)) S { + Ty X; + +public: + const Ty *get() const { + return &X; // expected-warning {{packed member 'X' of class or structure 'S<int>'}} + // expected-warning@-1 {{packed member 'X' of class or structure 'S<float>'}} + } +}; + +template <typename Ty> +void h(Ty *); + +void g1() { + S<int> s1; + s1.get(); // expected-note {{in instantiation of member function 'S<int>::get'}} + + S<char> s2; + s2.get(); + + S<float> s3; + s3.get(); // expected-note {{in instantiation of member function 'S<float>::get'}} +} diff --git a/test/SemaCXX/aggregate-init-cxx98.cpp b/test/SemaCXX/aggregate-init-cxx98.cpp new file mode 100644 index 000000000000..332801f0822c --- /dev/null +++ b/test/SemaCXX/aggregate-init-cxx98.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++98 -verify %s + +struct A { + A() = default; // expected-warning {{C++11}} + int n; +}; +A a = {0}; diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index ddaf33fc1bfa..7b6abd22acc7 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -4,8 +4,6 @@ // Verify that using an initializer list for a non-aggregate looks for // constructors.. -// Note that due to a (likely) standard bug, this is technically an aggregate, -// but we do not treat it as one. struct NonAggr1 { // expected-note 2 {{candidate constructor}} NonAggr1(int, int) { } // expected-note {{candidate constructor}} @@ -57,7 +55,7 @@ struct A { A(int); ~A(); - A(const A&) = delete; // expected-note 2 {{'A' has been explicitly marked deleted here}} + A(const A&) = delete; // expected-note 0-2{{'A' has been explicitly marked deleted here}} }; struct B { @@ -70,10 +68,16 @@ struct C { void f() { A as1[1] = { }; - A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}} + A as2[1] = { 1 }; +#if __cplusplus <= 201402L + // expected-error@-2 {{copying array element of type 'A' invokes deleted constructor}} +#endif B b1 = { }; - B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}} + B b2 = { 1 }; +#if __cplusplus <= 201402L + // expected-error@-2 {{copying member subobject of type 'A' invokes deleted constructor}} +#endif C c1 = { 1 }; } diff --git a/test/SemaCXX/ambig-user-defined-conversions.cpp b/test/SemaCXX/ambig-user-defined-conversions.cpp index 1a3c102f034c..276c1b07b5d9 100644 --- a/test/SemaCXX/ambig-user-defined-conversions.cpp +++ b/test/SemaCXX/ambig-user-defined-conversions.cpp @@ -65,3 +65,8 @@ namespace rdar8876150 { bool f(D d) { return !d; } // expected-error{{ambiguous conversion from derived class 'rdar8876150::D' to base class 'rdar8876150::A':}} } + +namespace assignment { + struct A { operator short(); operator bool(); }; // expected-note 2{{candidate}} + void f(int n, A a) { n = a; } // expected-error{{ambiguous}} +} diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp index b4e9f4609f67..a553f0d21000 100644 --- a/test/SemaCXX/attr-gnu.cpp +++ b/test/SemaCXX/attr-gnu.cpp @@ -27,3 +27,19 @@ public: void test3() __attribute__((cf_unknown_transfer)) override {} // Ok, not known to GCC. }; } + +template<typename T> +union Tu { T b; } __attribute__((transparent_union)); // expected-warning {{'transparent_union' attribute ignored}} + +template<typename T> +union Tu2 { int x; T b; } __attribute__((transparent_union)); // expected-warning {{'transparent_union' attribute ignored}} + +union Tu3 { int x; } __attribute((transparent_union)); // expected-warning {{'transparent_union' attribute ignored}} + +void tuTest1(Tu<int> u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu<int>' for 1st argument}} +void tuTest2(Tu3 u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu3' for 1st argument}} +void tu() { + int x = 2; + tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}} + tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}} +} diff --git a/test/SemaCXX/attr-no-sanitize-address.cpp b/test/SemaCXX/attr-no-sanitize-address.cpp index 9499742ac570..127129c948a0 100644 --- a/test/SemaCXX/attr-no-sanitize-address.cpp +++ b/test/SemaCXX/attr-no-sanitize-address.cpp @@ -21,9 +21,6 @@ int noanal_testfn(int y) { return x; } -int noanal_test_var NO_SANITIZE_ADDRESS; // \ - // expected-error {{'no_sanitize_address' attribute only applies to functions}} - class NoanalFoo { private: int test_field NO_SANITIZE_ADDRESS; // \ diff --git a/test/SemaCXX/attr-no-sanitize.cpp b/test/SemaCXX/attr-no-sanitize.cpp index 741f76062821..965def6f0254 100644 --- a/test/SemaCXX/attr-no-sanitize.cpp +++ b/test/SemaCXX/attr-no-sanitize.cpp @@ -2,8 +2,6 @@ // RUN: not %clang_cc1 -std=c++11 -ast-dump %s | FileCheck --check-prefix=DUMP %s // RUN: not %clang_cc1 -std=c++11 -ast-print %s | FileCheck --check-prefix=PRINT %s -int v1 __attribute__((no_sanitize("address"))); // expected-error{{'no_sanitize' attribute only applies to functions and methods}} - int f1() __attribute__((no_sanitize)); // expected-error{{'no_sanitize' attribute takes at least 1 argument}} int f2() __attribute__((no_sanitize(1))); // expected-error{{'no_sanitize' attribute requires a string}} diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp index 6df008dffa81..a8e71db73702 100644 --- a/test/SemaCXX/attr-noreturn.cpp +++ b/test/SemaCXX/attr-noreturn.cpp @@ -167,7 +167,7 @@ namespace destructor_tests { // PR5620 void f0() __attribute__((__noreturn__)); -void f1(void (*)()); +void f1(void (*)()); void f2() { f1(f0); } // Taking the address of a noreturn function diff --git a/test/SemaCXX/attr-require-constant-initialization.cpp b/test/SemaCXX/attr-require-constant-initialization.cpp new file mode 100644 index 000000000000..73f81cb1fc1d --- /dev/null +++ b/test/SemaCXX/attr-require-constant-initialization.cpp @@ -0,0 +1,282 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++03 %s +// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++14 %s +// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_TWO \ +// RUN: -Wglobal-constructors -std=c++14 %s +// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_THREE -xc %s + +#define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}} + +int ReturnInt(); + +struct PODType { + int value; + int value2; +}; + +#if defined(__cplusplus) + +#if __cplusplus >= 201103L +struct LitType { + constexpr LitType() : value(0) {} + constexpr LitType(int x) : value(x) {} + LitType(void *) : value(-1) {} + int value; +}; +#endif + +struct NonLit { +#if __cplusplus >= 201402L + constexpr NonLit() : value(0) {} + constexpr NonLit(int x) : value(x) {} +#else + NonLit() : value(0) {} + NonLit(int x) : value(x) {} +#endif + NonLit(void *) : value(-1) {} + ~NonLit() {} + int value; +}; + +struct StoresNonLit { +#if __cplusplus >= 201402L + constexpr StoresNonLit() : obj() {} + constexpr StoresNonLit(int x) : obj(x) {} +#else + StoresNonLit() : obj() {} + StoresNonLit(int x) : obj(x) {} +#endif + StoresNonLit(void *p) : obj(p) {} + NonLit obj; +}; + +#endif // __cplusplus + + +#if defined(TEST_ONE) // Test semantics of attribute + +// Test diagnostics when attribute is applied to non-static declarations. +void test_func_local(ATTR int param) { // expected-error {{only applies to variables with static or thread}} + ATTR int x = 42; // expected-error {{only applies to variables with static or thread}} + ATTR extern int y; +} +struct ATTR class_mem { // expected-error {{only applies to variables with static or thread}} + ATTR int x; // expected-error {{only applies to variables with static or thread}} +}; + +// [basic.start.static]p2.1 +// if each full-expression (including implicit conversions) that appears in +// the initializer of a reference with static or thread storage duration is +// a constant expression (5.20) and the reference is bound to a glvalue +// designating an object with static storage duration, to a temporary object +// (see 12.2) or subobject thereof, or to a function; + +// Test binding to a static glvalue +const int glvalue_int = 42; +const int glvalue_int2 = ReturnInt(); +ATTR const int &glvalue_ref ATTR = glvalue_int; +ATTR const int &glvalue_ref2 ATTR = glvalue_int2; +ATTR __thread const int &glvalue_ref_tl = glvalue_int; + +void test_basic_start_static_2_1() { + const int non_global = 42; + ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}} + // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + ATTR static const int &global_init = glvalue_int; + ATTR static const int &temp_init = 42; +} + +ATTR const int &temp_ref = 42; +ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + +#if __cplusplus >= 201103L +ATTR const LitType &lit_temp_ref = 42; +ATTR const int &subobj_ref = LitType{}.value; +#endif + +ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + +struct TT1 { + ATTR static const int &no_init; + ATTR static const int &glvalue_init; + ATTR static const int &temp_init; + ATTR static const int &subobj_init; +#if __cplusplus >= 201103L + ATTR static thread_local const int &tl_glvalue_init; + ATTR static thread_local const int &tl_temp_init; // expected-note {{required by 'require_constant_initializer' attribute here}} +#endif +}; +const int &TT1::glvalue_init = glvalue_int; +const int &TT1::temp_init = 42; +const int &TT1::subobj_init = PODType().value; +#if __cplusplus >= 201103L +thread_local const int &TT1::tl_glvalue_init = glvalue_int; +thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}} +#endif + +// [basic.start.static]p2.2 +// if an object with static or thread storage duration is initialized by a +// constructor call, and if the initialization full-expression is a constant +// initializer for the object; + +void test_basic_start_static_2_2() { +#if __cplusplus < 201103L + ATTR static PODType pod; +#else + ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#endif + ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}} + // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + +#if __cplusplus >= 201103L + constexpr LitType l; + ATTR static LitType static_lit = l; + ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}} + // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} + // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + ATTR thread_local LitType tls = 42; +#endif +} + +struct TT2 { + ATTR static PODType pod_noinit; +#if __cplusplus >= 201103L +// expected-note@-2 {{required by 'require_constant_initializer' attribute here}} +#endif + ATTR static PODType pod_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}} +#if __cplusplus >= 201402L + ATTR static constexpr LitType lit = {}; + ATTR static const NonLit non_lit; + ATTR static const NonLit non_lit_list_init; + ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}} +#endif +}; +PODType TT2::pod_noinit; +#if __cplusplus >= 201103L +// expected-error@-2 {{variable does not have a constant initializer}} +#endif +PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}} +#if __cplusplus >= 201402L +const NonLit TT2::non_lit(42); +const NonLit TT2::non_lit_list_init = {42}; +const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}} +#endif + +#if __cplusplus >= 201103L +ATTR LitType lit_ctor; +ATTR LitType lit_ctor2{}; +ATTR LitType lit_ctor3 = {}; +ATTR __thread LitType lit_ctor_tl = {}; + +#if __cplusplus >= 201402L +ATTR NonLit nl_ctor; +ATTR NonLit nl_ctor2{}; +ATTR NonLit nl_ctor3 = {}; +ATTR thread_local NonLit nl_ctor_tl = {}; +ATTR StoresNonLit snl; +#else +ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#endif + +// Non-literal types cannot appear in the initializer of a non-literal type. +ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR int lit_in_init = LitType{42}.value; +#endif + +// [basic.start.static]p2.3 +// if an object with static or thread storage duration is not initialized by a +// constructor call and if either the object is value-initialized or every +// full-expression that appears in its initializer is a constant expression. +void test_basic_start_static_2_3() { + ATTR static int static_local = 42; + ATTR static int static_local2; // zero-initialization takes place +#if __cplusplus >= 201103L + ATTR thread_local int tl_local = 42; +#endif +} + +ATTR int no_init; // zero initialization takes place +ATTR int arg_init = 42; +ATTR PODType pod_init = {}; +ATTR PODType pod_missing_init = {42 /* should have second arg */}; +ATTR PODType pod_full_init = {1, 2}; +ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + +#if __cplusplus >= 201103L +ATTR int val_init{}; +ATTR int brace_init = {}; +#endif + +ATTR __thread int tl_init = 0; +typedef const char *StrType; + +#if __cplusplus >= 201103L + +// Test that the validity of the selected constructor is checked, not just the +// initializer +struct NotC { + constexpr NotC(void *) {} + NotC(int) {} +}; +template <class T> +struct TestCtor { + constexpr TestCtor(int x) : value(x) {} + T value; +}; +ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#endif + +// Test various array types +ATTR const char *foo[] = {"abc", "def"}; +ATTR PODType bar[] = {{}, {123, 456}}; + +#elif defined(TEST_TWO) // Test for duplicate warnings +struct NotC { + constexpr NotC(void *) {} + NotC(int) {} // expected-note 2 {{declared here}} +}; +template <class T> +struct TestCtor { + constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}} + T value; +}; + +ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}} +// expected-warning@-1 {{declaration requires a global destructor}} +// expected-note@-2 {{required by 'require_constant_initializer' attribute here}} +LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}} +NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}} +constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}} +// expected-note@-1 {{in call to 'TestCtor(42)'}} +ATTR constexpr TestCtor<NotC> inval_constexpr2(42); // expected-error {{must be initialized by a constant expression}} +// expected-note@-1 {{in call to 'TestCtor(42)'}} + +#elif defined(TEST_THREE) +#if defined(__cplusplus) +#error This test requires C +#endif +// Test that using the attribute in C results in a diagnostic +ATTR int x = 0; // expected-warning {{attribute ignored}} +#else +#error No test case specified +#endif // defined(TEST_N) diff --git a/test/SemaCXX/attr-swiftcall.cpp b/test/SemaCXX/attr-swiftcall.cpp index fd17aae18523..eb9538e31044 100644 --- a/test/SemaCXX/attr-swiftcall.cpp +++ b/test/SemaCXX/attr-swiftcall.cpp @@ -17,16 +17,16 @@ void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL; void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL; void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}} -void error_result_bad_position(ERROR_RESULT void **error, int last) SWIFTCALL; // expected-error {{'swift_error_result' parameter must be last parameter of function}} void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}} void error_result_bad_type(CONTEXT void *context, ERROR_RESULT int error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int'}} void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int *'}} void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL; +void error_result_okay(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL; void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}} -void context_bad_position(CONTEXT void *context, int x) SWIFTCALL; // expected-error {{'swift_context' parameter can only be followed by 'swift_error_result' parameter}} void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}} void context_okay(CONTEXT void *context) SWIFTCALL; +void context_okay(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL; template <class T> void indirect_result_temp_okay1(INDIRECT_RESULT T *out) SWIFTCALL; template <class T> void indirect_result_temp_okay2(INDIRECT_RESULT T out) SWIFTCALL; // expected-note {{candidate template ignored: substitution failure [with T = int]: 'swift_indirect_result' parameter must have pointer type; type here is 'int'}} diff --git a/test/SemaCXX/builtin-exception-spec.cpp b/test/SemaCXX/builtin-exception-spec.cpp index 590cd3c35d4e..9845172bcd72 100644 --- a/test/SemaCXX/builtin-exception-spec.cpp +++ b/test/SemaCXX/builtin-exception-spec.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -verify %s +// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -verify -std=c++1z %s // expected-no-diagnostics #include <malloc.h> diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp index 69bdfa614517..f26931b55bdb 100644 --- a/test/SemaCXX/builtins.cpp +++ b/test/SemaCXX/builtins.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11 +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11 -fcxx-exceptions +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++1z -fcxx-exceptions typedef const struct __CFString * CFStringRef; #define CFSTR __builtin___CFStringMakeConstantString @@ -44,3 +45,11 @@ void no_ms_builtins() { __noop(1); // expected-error {{use of undeclared}} __debugbreak(); // expected-error {{use of undeclared}} } + +struct FILE; +extern "C" int vfprintf(FILE *__restrict, const char *__restrict, + __builtin_va_list va); + +void synchronize_args() { + __sync_synchronize(0); // expected-error {{too many arguments}} +} diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp index ef0a524f92f1..0528b044fb1f 100644 --- a/test/SemaCXX/compare.cpp +++ b/test/SemaCXX/compare.cpp @@ -201,9 +201,10 @@ int test1(int i) { enum E { e }; void test2(int i, void *vp) { + if (&i == vp) { } // ok if (test1 == vp) { } // expected-warning{{equality comparison between function pointer and void pointer}} if (test1 == e) { } // expected-error{{comparison between pointer and integer}} - if (vp < 0) { } + if (vp < 0) { } // expected-error {{comparison between pointer and zero}} if (test1 < e) { } // expected-error{{comparison between pointer and integer}} } diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp index 06fc8f43855d..dddf424caa2e 100644 --- a/test/SemaCXX/composite-pointer-type.cpp +++ b/test/SemaCXX/composite-pointer-type.cpp @@ -53,8 +53,8 @@ bool f(Matrix4 m1, const Matrix4 m2) { // PR6346 bool f1(bool b, void **p, const void **q) { - if (p == q) // expected-warning{{comparison of distinct pointer types ('void **' and 'const void **') uses non-standard composite pointer type 'const void *const *'}} + if (p == q) return false; - return b? p : q; // expected-warning{{incompatible operand types ('void **' and 'const void **') use non-standard composite pointer type 'const void *const *'}} + return b? p : q; } diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp index 3fc61505dfee..5480b1fef44d 100644 --- a/test/SemaCXX/compound-literal.cpp +++ b/test/SemaCXX/compound-literal.cpp @@ -86,3 +86,13 @@ int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a c template<unsigned> struct Value { }; template<typename T> int &check_narrowed(Value<sizeof((T){1.1})>); + +#if __cplusplus >= 201103L +// Compound literals in global lambdas have automatic storage duration +// and are not subject to the constant-initialization rules. +int computed_with_lambda = [] { + int x = 5; + int result = ((int[]) { x, x + 2, x + 4, x + 6 })[0]; + return result; +}(); +#endif diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index c12efc0be7ef..5025990cfd36 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -262,7 +262,7 @@ namespace PR6757 { struct Foo2 { }; struct Foo3 { - Foo3(); + Foo3(); // expected-note{{requires 0 arguments}} Foo3(Foo3&); // expected-note{{would lose const qualifier}} }; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index e2b3f091f70f..581a524339e7 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -279,17 +279,17 @@ static_assert(&s.x > &s.y, "false"); // expected-error {{false}} static_assert(0 == &y, "false"); // expected-error {{false}} static_assert(0 != &y, ""); -constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}} -constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}} -constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}} -constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n3 = (int*)0 <= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n4 = (int*)0 >= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n5 = (int*)0 < &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n6 = (int*)0 > &y; // expected-error {{must be initialized by a constant expression}} static_assert(&x == 0, "false"); // expected-error {{false}} static_assert(&x != 0, ""); -constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}} -constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}} -constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}} -constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n9 = &x <= (int*)0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n10 = &x >= (int*)0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n11 = &x < (int*)0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n12 = &x > (int*)0; // expected-error {{must be initialized by a constant expression}} static_assert(&x == &x, ""); static_assert(&x != &x, "false"); // expected-error {{false}} @@ -386,6 +386,18 @@ namespace FakeInitList { constexpr init_list_2_init_list_3_ints ils = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } }; } +namespace ConstAddedByReference { + const int &r = (0); + constexpr int n = r; + + struct A { constexpr operator int() const { return 0; }}; + struct B { constexpr operator const int() const { return 0; }}; + const int &ra = A(); + const int &rb = B(); + constexpr int na = ra; + constexpr int nb = rb; +} + } constexpr int strcmp_ce(const char *p, const char *q) { @@ -554,6 +566,21 @@ struct ArrayRVal { }; static_assert(ArrayRVal().elems[3].f() == 0, ""); +namespace CopyCtor { + struct A { + constexpr A() {} + constexpr A(const A &) {} + }; + struct B { + A a; + int arr[10]; + }; + constexpr B b{{}, {1, 2, 3, 4, 5}}; + constexpr B c = b; + static_assert(c.arr[2] == 3, ""); + static_assert(c.arr[7] == 0, ""); +} + constexpr int selfref[2][2][2] = { selfref[1][1][1] + 1, selfref[0][0][0] + 1, selfref[1][0][1] + 1, selfref[0][1][0] + 1, @@ -1156,7 +1183,7 @@ constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant exp constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}} struct T { int n; }; -const T t = { 42 }; // expected-note {{declared here}} +const T t = { 42 }; constexpr int f(volatile int &&r) { return r; // expected-note {{read of volatile-qualified type 'volatile int'}} @@ -1168,7 +1195,7 @@ struct S { int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}} int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}} int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}} - int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}} + int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}} expected-warning{{expression is not an integral constant expression}} expected-note{{read of non-constexpr variable 't' is not allowed}} }; } @@ -1467,13 +1494,26 @@ namespace VLASizeof { } namespace CompoundLiteral { - // FIXME: - // We don't model the semantics of this correctly: the compound literal is - // represented as a prvalue in the AST, but actually behaves like an lvalue. - // We treat the compound literal as a temporary and refuse to produce a - // pointer to it. This is OK: we're not required to treat this as a constant - // in C++, and in C we model compound literals as lvalues. - constexpr int *p = (int*)(int[1]){0}; // expected-warning {{C99}} expected-error {{constant expression}} expected-note 2{{temporary}} + // Matching GCC, file-scope array compound literals initialized by constants + // are lifetime-extended. + constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} + static_assert(*p == 3, ""); + static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}} + + // Other kinds are not. + struct X { int a[2]; }; + constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary array}} + // expected-error@-1 {{constant expression}} + // expected-note@-2 {{pointer to subobject of temporary}} + // expected-note@-3 {{temporary created here}} + + void f() { + static constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} + // expected-error@-1 {{constant expression}} + // expected-note@-2 {{pointer to subobject of temporary}} + // expected-note@-3 {{temporary created here}} + static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}} + } } namespace Vector { @@ -1862,8 +1902,8 @@ namespace ZeroSizeTypes { namespace BadDefaultInit { template<int N> struct X { static const int n = N; }; - struct A { - int k = // expected-error {{cannot use defaulted default constructor of 'A' within the class outside of member functions because 'k' has an initializer}} + struct A { // expected-error {{default member initializer for 'k' needed within definition of enclosing class}} + int k = // expected-note {{default member initializer declared here}} X<A().k>::n; // expected-error {{not a constant expression}} expected-note {{implicit default constructor for 'BadDefaultInit::A' first required here}} }; @@ -2066,3 +2106,33 @@ namespace InheritedCtor { constexpr Z z(1); static_assert(z.w == 1 && z.x == 2 && z.y == 3 && z.z == 4, ""); } + + +namespace PR28366 { +namespace ns1 { + +void f(char c) { //expected-note2{{declared here}} + struct X { + static constexpr char f() { //expected-error{{never produces a constant expression}} + return c; //expected-error{{reference to local}} expected-note{{non-const variable}} + } + }; + int I = X::f(); +} + +void g() { + const int c = 'c'; + static const int d = 'd'; + struct X { + static constexpr int f() { + return c + d; + } + }; + static_assert(X::f() == 'c' + 'd',""); +} + + +} // end ns1 + +} //end ns PR28366 + diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp index f8103224af89..dfdf50ad5484 100644 --- a/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/test/SemaCXX/constant-expression-cxx1y.cpp @@ -957,3 +957,23 @@ namespace PR27989 { } static_assert(f(0) == 1, ""); } + +namespace const_char { +template <int N> +constexpr int sum(const char (&Arr)[N]) { + int S = 0; + for (unsigned I = 0; I != N; ++I) + S += Arr[I]; // expected-note 2{{read of non-constexpr variable 'Cs' is not allowed}} + return S; +} + +// As an extension, we support evaluating some things that are `const` as though +// they were `constexpr` when folding, but it should not be allowed in normal +// constexpr evaluation. +const char Cs[] = {'a', 'b'}; +void foo() __attribute__((enable_if(sum(Cs) == 'a' + 'b', ""))); +void run() { foo(); } + +static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral constant expression}} expected-note{{in call to 'sum(Cs)'}} +constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}} +} diff --git a/test/SemaCXX/constant-expression-cxx1z.cpp b/test/SemaCXX/constant-expression-cxx1z.cpp index e84de44d374a..a48c9b11b886 100644 --- a/test/SemaCXX/constant-expression-cxx1z.cpp +++ b/test/SemaCXX/constant-expression-cxx1z.cpp @@ -25,3 +25,24 @@ namespace BaseClassAggregateInit { constexpr D d5 = { __INT_MAX__ }; // expected-error {{must be initialized by a constant expression}} // expected-note-re@-1 {{in call to 'A({{.*}})'}} } + +namespace NoexceptFunctionTypes { + template<typename T> constexpr bool f() noexcept(true) { return true; } + constexpr bool (*fp)() = f<int>; + static_assert(f<int>()); + static_assert(fp()); + + template<typename T> struct A { + constexpr bool f() noexcept(true) { return true; } + constexpr bool g() { return f(); } + constexpr bool operator()() const noexcept(true) { return true; } + }; + static_assert(A<int>().f()); + static_assert(A<int>().g()); + static_assert(A<int>()()); +} + +namespace Cxx17CD_NB_GB19 { + const int &r = 0; + constexpr int n = r; +} diff --git a/test/SemaCXX/constexpr-string.cpp b/test/SemaCXX/constexpr-string.cpp new file mode 100644 index 000000000000..944038bc163a --- /dev/null +++ b/test/SemaCXX/constexpr-string.cpp @@ -0,0 +1,201 @@ +// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -pedantic +// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -pedantic -fno-signed-char +// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -pedantic -fno-wchar -Dwchar_t=__WCHAR_TYPE__ + +# 6 "/usr/include/string.h" 1 3 4 +extern "C" { + typedef decltype(sizeof(int)) size_t; + + extern size_t strlen(const char *p); + + extern int strcmp(const char *s1, const char *s2); + extern int strncmp(const char *s1, const char *s2, size_t n); + extern int memcmp(const void *s1, const void *s2, size_t n); + + extern char *strchr(const char *s, int c); + extern void *memchr(const void *s, int c, size_t n); +} +# 19 "SemaCXX/constexpr-string.cpp" 2 + +# 21 "/usr/include/wchar.h" 1 3 4 +extern "C" { + extern size_t wcslen(const wchar_t *p); + + extern int wcscmp(const wchar_t *s1, const wchar_t *s2); + extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); + extern int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); + + extern wchar_t *wcschr(const wchar_t *s, wchar_t c); + extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); +} + +# 33 "SemaCXX/constexpr-string.cpp" 2 +namespace Strlen { + constexpr int n = __builtin_strlen("hello"); // ok + static_assert(n == 5); + constexpr int wn = __builtin_wcslen(L"hello"); // ok + static_assert(wn == 5); + constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}} + constexpr int wm = wcslen(L"hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcslen' cannot be used in a constant expression}} + + // Make sure we can evaluate a call to strlen. + int arr[3]; // expected-note 2{{here}} + int k = arr[strlen("hello")]; // expected-warning {{array index 5}} + int wk = arr[wcslen(L"hello")]; // expected-warning {{array index 5}} +} + +namespace StrcmpEtc { + constexpr char kFoobar[6] = {'f','o','o','b','a','r'}; + constexpr char kFoobazfoobar[12] = {'f','o','o','b','a','z','f','o','o','b','a','r'}; + + static_assert(__builtin_strcmp("abab", "abab") == 0); + static_assert(__builtin_strcmp("abab", "abba") == -1); + static_assert(__builtin_strcmp("abab", "abaa") == 1); + static_assert(__builtin_strcmp("ababa", "abab") == 1); + static_assert(__builtin_strcmp("abab", "ababa") == -1); + static_assert(__builtin_strcmp("abab\0banana", "abab") == 0); + static_assert(__builtin_strcmp("abab", "abab\0banana") == 0); + static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0); + static_assert(__builtin_strcmp(0, "abab") == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + static_assert(__builtin_strcmp("abab", 0) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + + static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar) == -1); // FIXME: Should we reject this? + static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + + static_assert(__builtin_strncmp("abaa", "abba", 5) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 4) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 3) == -1); + static_assert(__builtin_strncmp("abaa", "abba", 2) == 0); + static_assert(__builtin_strncmp("abaa", "abba", 1) == 0); + static_assert(__builtin_strncmp("abaa", "abba", 0) == 0); + static_assert(__builtin_strncmp(0, 0, 0) == 0); + static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0); + + static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar, 6) == -1); + static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar, 7) == -1); // FIXME: Should we reject this? + static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar + 6, 6) == 0); + static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + + static_assert(__builtin_memcmp("abaa", "abba", 3) == -1); + static_assert(__builtin_memcmp("abaa", "abba", 2) == 0); + static_assert(__builtin_memcmp(0, 0, 0) == 0); + static_assert(__builtin_memcmp("abab\0banana", "abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 100) == -1); // FIXME: Should we reject this? + static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 7) == -1); + static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1); + static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 5) == 0); + + constexpr int a = strcmp("hello", "world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strcmp' cannot be used in a constant expression}} + constexpr int b = strncmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strncmp' cannot be used in a constant expression}} + constexpr int c = memcmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memcmp' cannot be used in a constant expression}} +} + +namespace WcscmpEtc { + constexpr wchar_t kFoobar[6] = {L'f',L'o',L'o',L'b',L'a',L'r'}; + constexpr wchar_t kFoobazfoobar[12] = {L'f',L'o',L'o',L'b',L'a',L'z',L'f',L'o',L'o',L'b',L'a',L'r'}; + + static_assert(__builtin_wcscmp(L"abab", L"abab") == 0); + static_assert(__builtin_wcscmp(L"abab", L"abba") == -1); + static_assert(__builtin_wcscmp(L"abab", L"abaa") == 1); + static_assert(__builtin_wcscmp(L"ababa", L"abab") == 1); + static_assert(__builtin_wcscmp(L"abab", L"ababa") == -1); + static_assert(__builtin_wcscmp(L"abab\0banana", L"abab") == 0); + static_assert(__builtin_wcscmp(L"abab", L"abab\0banana") == 0); + static_assert(__builtin_wcscmp(L"abab\0banana", L"abab\0canada") == 0); + static_assert(__builtin_wcscmp(0, L"abab") == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + static_assert(__builtin_wcscmp(L"abab", 0) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + + static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar) == -1); // FIXME: Should we reject this? + static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar + 6) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + + static_assert(__builtin_wcsncmp(L"abaa", L"abba", 5) == -1); + static_assert(__builtin_wcsncmp(L"abaa", L"abba", 4) == -1); + static_assert(__builtin_wcsncmp(L"abaa", L"abba", 3) == -1); + static_assert(__builtin_wcsncmp(L"abaa", L"abba", 2) == 0); + static_assert(__builtin_wcsncmp(L"abaa", L"abba", 1) == 0); + static_assert(__builtin_wcsncmp(L"abaa", L"abba", 0) == 0); + static_assert(__builtin_wcsncmp(0, 0, 0) == 0); + static_assert(__builtin_wcsncmp(L"abab\0banana", L"abab\0canada", 100) == 0); + + static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 6) == -1); + static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 7) == -1); // FIXME: Should we reject this? + static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 6) == 0); + static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + + static_assert(__builtin_wmemcmp(L"abaa", L"abba", 3) == -1); + static_assert(__builtin_wmemcmp(L"abaa", L"abba", 2) == 0); + static_assert(__builtin_wmemcmp(0, 0, 0) == 0); + static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 100) == -1); // FIXME: Should we reject this? + static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 7) == -1); + static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 6) == -1); + static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 5) == 0); + + constexpr int a = wcscmp(L"hello", L"world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcscmp' cannot be used in a constant expression}} + constexpr int b = wcsncmp(L"hello", L"world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcsncmp' cannot be used in a constant expression}} + constexpr int c = wmemcmp(L"hello", L"world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wmemcmp' cannot be used in a constant expression}} +} + +namespace StrchrEtc { + constexpr const char *kStr = "abca\xff\0d"; + constexpr char kFoo[] = {'f', 'o', 'o'}; + static_assert(__builtin_strchr(kStr, 'a') == kStr); + static_assert(__builtin_strchr(kStr, 'b') == kStr + 1); + static_assert(__builtin_strchr(kStr, 'c') == kStr + 2); + static_assert(__builtin_strchr(kStr, 'd') == nullptr); + static_assert(__builtin_strchr(kStr, 'e') == nullptr); + static_assert(__builtin_strchr(kStr, '\0') == kStr + 5); + static_assert(__builtin_strchr(kStr, 'a' + 256) == nullptr); + static_assert(__builtin_strchr(kStr, 'a' - 256) == nullptr); + static_assert(__builtin_strchr(kStr, '\xff') == kStr + 4); + static_assert(__builtin_strchr(kStr, '\xff' + 256) == nullptr); + static_assert(__builtin_strchr(kStr, '\xff' - 256) == nullptr); + static_assert(__builtin_strchr(kFoo, 'o') == kFoo + 1); + static_assert(__builtin_strchr(kFoo, 'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_strchr(nullptr, 'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + + static_assert(__builtin_memchr(kStr, 'a', 0) == nullptr); + static_assert(__builtin_memchr(kStr, 'a', 1) == kStr); + static_assert(__builtin_memchr(kStr, '\0', 5) == nullptr); + static_assert(__builtin_memchr(kStr, '\0', 6) == kStr + 5); + static_assert(__builtin_memchr(kStr, '\xff', 8) == kStr + 4); + static_assert(__builtin_memchr(kStr, '\xff' + 256, 8) == kStr + 4); + static_assert(__builtin_memchr(kStr, '\xff' - 256, 8) == kStr + 4); + static_assert(__builtin_memchr(kFoo, 'x', 3) == nullptr); + static_assert(__builtin_memchr(kFoo, 'x', 4) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr); // FIXME: Should we reject this? + + constexpr bool a = !strchr("hello", 'h'); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strchr' cannot be used in a constant expression}} + constexpr bool b = !memchr("hello", 'h', 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memchr' cannot be used in a constant expression}} +} + +namespace WcschrEtc { + constexpr const wchar_t *kStr = L"abca\xffff\0dL"; + constexpr wchar_t kFoo[] = {L'f', L'o', L'o'}; + static_assert(__builtin_wcschr(kStr, L'a') == kStr); + static_assert(__builtin_wcschr(kStr, L'b') == kStr + 1); + static_assert(__builtin_wcschr(kStr, L'c') == kStr + 2); + static_assert(__builtin_wcschr(kStr, L'd') == nullptr); + static_assert(__builtin_wcschr(kStr, L'e') == nullptr); + static_assert(__builtin_wcschr(kStr, L'\0') == kStr + 5); + static_assert(__builtin_wcschr(kStr, L'a' + 256) == nullptr); + static_assert(__builtin_wcschr(kStr, L'a' - 256) == nullptr); + static_assert(__builtin_wcschr(kStr, L'\xffff') == kStr + 4); + static_assert(__builtin_wcschr(kFoo, L'o') == kFoo + 1); + static_assert(__builtin_wcschr(kFoo, L'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_wcschr(nullptr, L'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + + static_assert(__builtin_wmemchr(kStr, L'a', 0) == nullptr); + static_assert(__builtin_wmemchr(kStr, L'a', 1) == kStr); + static_assert(__builtin_wmemchr(kStr, L'\0', 5) == nullptr); + static_assert(__builtin_wmemchr(kStr, L'\0', 6) == kStr + 5); + static_assert(__builtin_wmemchr(kStr, L'\xffff', 8) == kStr + 4); + static_assert(__builtin_wmemchr(kFoo, L'x', 3) == nullptr); + static_assert(__builtin_wmemchr(kFoo, L'x', 4) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}} + static_assert(__builtin_wmemchr(nullptr, L'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}} + static_assert(__builtin_wmemchr(nullptr, L'x', 0) == nullptr); // FIXME: Should we reject this? + + constexpr bool a = !wcschr(L"hello", L'h'); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcschr' cannot be used in a constant expression}} + constexpr bool b = !wmemchr(L"hello", L'h', 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wmemchr' cannot be used in a constant expression}} +} diff --git a/test/SemaCXX/constexpr-strlen.cpp b/test/SemaCXX/constexpr-strlen.cpp deleted file mode 100644 index 5e28e7f0ce5f..000000000000 --- a/test/SemaCXX/constexpr-strlen.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -pedantic - -# 1 "/usr/include/string.h" 1 3 4 -extern "C" { - typedef decltype(sizeof(int)) size_t; - extern size_t strlen(const char *p); -} - -# 10 "SemaCXX/constexpr-strlen.cpp" 2 -constexpr int n = __builtin_strlen("hello"); // ok -constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}} - -// Make sure we can evaluate a call to strlen. -int arr[3]; // expected-note {{here}} -int k = arr[strlen("hello")]; // expected-warning {{array index 5}} diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp index 3528fdcd8816..53271e0da3fa 100644 --- a/test/SemaCXX/constexpr-value-init.cpp +++ b/test/SemaCXX/constexpr-value-init.cpp @@ -34,4 +34,13 @@ struct V : virtual C {}; template<typename T> struct Z : T { constexpr Z() : V() {} }; -constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{virtual base class}} +constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{non-literal type 'Z<V>'}} + +struct E { + A a[2]; +}; +constexpr E e; // ok +static_assert(e.a[0].a == 1, ""); +static_assert(e.a[0].b == 2, ""); +static_assert(e.a[1].a == 1, ""); +static_assert(e.a[1].b == 2, ""); diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 3f494cce8ce3..c725a0d5b7c1 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -434,8 +434,12 @@ namespace PR18234 { struct A { operator enum E { e } (); // expected-error {{'PR18234::A::E' cannot be defined in a type specifier}} operator struct S { int n; } (); // expected-error {{'PR18234::A::S' cannot be defined in a type specifier}} + // expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'struct A' to 'const PR18234::A::S &' for 1st argument}} +#if __cplusplus >= 201103L + // expected-note@-3 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'struct A' to 'PR18234::A::S &&' for 1st argument}} +#endif } a; - A::S s = a; + A::S s = a; // expected-error {{no viable conversion from 'struct A' to 'A::S'}} A::E e = a; // expected-note {{here}} bool k1 = e == A::e; // expected-error {{no member named 'e'}} bool k2 = e.n == 0; diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index 7b86cecdbcef..dcd64fa2ec8a 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -50,7 +50,7 @@ namespace test1 { namespace test2 { struct A { unsigned int x : 2; - A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} + A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to 2}} }; } diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp index 798582c149cf..d6ad6577895f 100644 --- a/test/SemaCXX/copy-assignment.cpp +++ b/test/SemaCXX/copy-assignment.cpp @@ -1,4 +1,11 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +#if __cplusplus >= 201103L +// expected-note@+3 2 {{candidate constructor}} +// expected-note@+2 {{passing argument to parameter here}} +#endif struct A { }; @@ -7,6 +14,9 @@ struct ConvertibleToA { }; struct ConvertibleToConstA { +#if __cplusplus >= 201103L +// expected-note@+2 {{candidate function}} +#endif operator const A(); }; @@ -69,6 +79,9 @@ void test() { na = a; na = constA; na = convertibleToA; +#if __cplusplus >= 201103L +// expected-error@+2 {{no viable conversion}} +#endif na = convertibleToConstA; na += a; // expected-error{{no viable overloaded '+='}} diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp index d219ee508f03..4f6c65cf550c 100644 --- a/test/SemaCXX/copy-initialization.cpp +++ b/test/SemaCXX/copy-initialization.cpp @@ -30,7 +30,7 @@ void test(const foo *P) { P->bar(); } // expected-error{{'bar' not viable: 'this namespace PR6757 { struct Foo { - Foo(); + Foo(); // expected-note{{not viable}} Foo(Foo&); // expected-note{{candidate constructor not viable}} }; @@ -71,3 +71,12 @@ namespace DR5 { const S b = 0; } } + +struct A {}; +struct B : A { + B(); + B(B&); + B(A); + B(int); +}; +B b = 0; // ok, calls B(int) then A(const A&) then B(A). diff --git a/test/SemaCXX/coreturn.cpp b/test/SemaCXX/coreturn.cpp new file mode 100644 index 000000000000..4c41ae95c513 --- /dev/null +++ b/test/SemaCXX/coreturn.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wno-unreachable-code -Wno-unused-value + +struct awaitable { + bool await_ready(); + void await_suspend(); // FIXME: coroutine_handle + void await_resume(); +} a; + +struct suspend_always { + bool await_ready() { return false; } + void await_suspend() {} + void await_resume() {} +}; + +struct suspend_never { + bool await_ready() { return true; } + void await_suspend() {} + void await_resume() {} +}; + +namespace std { +namespace experimental { + +template <class Ret, typename... T> +struct coroutine_traits { using promise_type = typename Ret::promise_type; }; + +template <class Promise = void> +struct coroutine_handle {}; +} +} + +struct promise_void { + void get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); +}; + +struct promise_float { + float get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); +}; + +struct promise_int { + int get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_value(int); +}; + +template <typename... T> +struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise_void; }; + +template <typename... T> +struct std::experimental::coroutine_traits<float, T...> { using promise_type = promise_float; }; + +template <typename... T> +struct std::experimental::coroutine_traits<int, T...> { using promise_type = promise_int; }; + +void test0() { co_await a; } +float test1() { co_await a; } + +int test2() { + co_await a; +} // expected-warning {{control reaches end of non-void coroutine}} + +int test3() { + co_await a; +b: + goto b; +} diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index e82cb62f12d4..a22383cd566b 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -1,4 +1,21 @@ -// RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s +// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s + +void no_coroutine_traits_bad_arg_await() { + co_await a; // expected-error {{include <experimental/coroutine>}} + // expected-error@-1 {{use of undeclared identifier 'a'}} +} + +void no_coroutine_traits_bad_arg_yield() { + co_yield a; // expected-error {{include <experimental/coroutine>}} + // expected-error@-1 {{use of undeclared identifier 'a'}} +} + + +void no_coroutine_traits_bad_arg_return() { + co_return a; // expected-error {{include <experimental/coroutine>}} + // expected-error@-1 {{use of undeclared identifier 'a'}} +} + struct awaitable { bool await_ready(); @@ -19,45 +36,64 @@ struct suspend_never { }; void no_coroutine_traits() { - co_await a; // expected-error {{need to include <coroutine>}} + co_await a; // expected-error {{need to include <experimental/coroutine>}} } namespace std { - template<typename ...T> struct coroutine_traits; // expected-note {{declared here}} -}; +namespace experimental { +template <typename... T> +struct coroutine_traits; // expected-note {{declared here}} +} +} template<typename Promise> struct coro {}; -template<typename Promise, typename... Ps> -struct std::coroutine_traits<coro<Promise>, Ps...> { +template <typename Promise, typename... Ps> +struct std::experimental::coroutine_traits<coro<Promise>, Ps...> { using promise_type = Promise; }; void no_specialization() { - co_await a; // expected-error {{implicit instantiation of undefined template 'std::coroutine_traits<void>'}} + co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits<void>'}} } -template<typename ...T> struct std::coroutine_traits<int, T...> {}; +template <typename... T> +struct std::experimental::coroutine_traits<int, T...> {}; int no_promise_type() { - co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<int>' has no member named 'promise_type'}} + co_await a; // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}} } -template<> struct std::coroutine_traits<double, double> { typedef int promise_type; }; +template <> +struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; }; double bad_promise_type(double) { - co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}} + co_await a; // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}} } -template<> struct std::coroutine_traits<double, int> { +template <> +struct std::experimental::coroutine_traits<double, int> { struct promise_type {}; }; double bad_promise_type_2(int) { - co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits<double, int>::promise_type'}} + co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits<double, int>::promise_type'}} } struct promise; // expected-note 2{{forward declaration}} -template<typename ...T> struct std::coroutine_traits<void, T...> { using promise_type = promise; }; +struct promise_void; +struct void_tag {}; +template <typename... T> +struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; }; +template <typename... T> +struct std::experimental::coroutine_traits<void, void_tag, T...> +{ using promise_type = promise_void; }; + +namespace std { +namespace experimental { +template <typename Promise = void> +struct coroutine_handle; +} +} - // FIXME: This diagnostic is terrible. +// FIXME: This diagnostic is terrible. void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}} // FIXME: This diagnostic doesn't make any sense. // expected-error@-2 {{incomplete definition of type 'promise'}} @@ -75,10 +111,16 @@ struct promise { awaitable yield_value(int); // expected-note 2{{candidate}} awaitable yield_value(yielded_thing); // expected-note 2{{candidate}} not_awaitable yield_value(void()); // expected-note 2{{candidate}} - void return_void(); void return_value(int); // expected-note 2{{here}} }; +struct promise_void { + void get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); +}; + void yield() { co_yield 0; co_yield {"foo", 1, 2}; @@ -95,10 +137,10 @@ void coreturn(int n) { if (n == 0) co_return 3; if (n == 1) - co_return {4}; + co_return {4}; // expected-warning {{braces around scalar initializer}} if (n == 2) co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}} - co_return; + co_return 42; } void mixed_yield() { @@ -111,11 +153,11 @@ void mixed_await() { return; // expected-error {{not allowed in coroutine}} } -void only_coreturn() { +void only_coreturn(void_tag) { co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}} } -void mixed_coreturn(bool b) { +void mixed_coreturn(void_tag, bool b) { if (b) // expected-warning@+1 {{'co_return' used in a function that uses neither}} co_return; // expected-note {{use of 'co_return'}} @@ -136,7 +178,19 @@ struct CtorDtor { } // FIXME: The spec says this is ill-formed. void operator=(CtorDtor&) { - co_yield 0; + co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}} + } + void operator=(CtorDtor const &) { + co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}} + } + void operator=(CtorDtor &&) { + co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}} + } + void operator=(CtorDtor const &&) { + co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}} + } + void operator=(int) { + co_await a; // OK. Not a special member } }; @@ -149,14 +203,19 @@ void unevaluated() { typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}} } -constexpr void constexpr_coroutine() { +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}} } void varargs_coroutine(const char *, ...) { co_await a; // expected-error {{'co_await' cannot be used in a varargs function}} } +auto deduced_return_coroutine() { + co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}} +} + struct outer {}; namespace dependent_operator_co_await_lookup { @@ -183,7 +242,8 @@ namespace dependent_operator_co_await_lookup { } struct yield_fn_tag {}; -template<> struct std::coroutine_traits<void, yield_fn_tag> { +template <> +struct std::experimental::coroutine_traits<void, yield_fn_tag> { struct promise_type { // FIXME: add an await_transform overload for functions awaitable yield_value(int()); @@ -266,3 +326,52 @@ struct bad_promise_5 { coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} co_await a; } + +struct bad_promise_6 { + coro<bad_promise_6> get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); + void return_value(int) const; + void return_value(int); +}; +coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} + co_await a; +} + +struct bad_promise_7 { + coro<bad_promise_7> get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); + void set_exception(int *); +}; +coro<bad_promise_7> no_std_current_exc() { + // expected-error@-1 {{you need to include <exception> before defining a coroutine that implicitly uses 'set_exception'}} + co_await a; +} + +namespace std { +int *current_exception(); +} + +struct bad_promise_8 { + coro<bad_promise_8> get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void return_void(); + void set_exception(); // expected-note {{function not viable}} + void set_exception(int *) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}} + void set_exception(void *); // expected-note {{candidate function}} +}; +coro<bad_promise_8> calls_set_exception() { + // expected-error@-1 {{call to unavailable member function 'set_exception'}} + co_await a; +} + +template<> struct std::experimental::coroutine_traits<int, int, const char**> +{ using promise_type = promise; }; + +int main(int, const char**) { + co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}} +} diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index 7ec9726095cb..f623dc765f88 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -87,35 +87,36 @@ namespace DefaultedFnExceptionSpec { template<typename T> struct Error { - // FIXME: Type canonicalization causes all the errors to point at the first - // declaration which has the type 'void () noexcept (T::error)'. We should - // get one error for 'Error<int>::Error()' and one for 'Error<int>::~Error()'. - void f() noexcept(T::error); // expected-error 2{{has no members}} - - Error() noexcept(T::error); - Error(const Error&) noexcept(T::error); - Error(Error&&) noexcept(T::error); - Error &operator=(const Error&) noexcept(T::error); - Error &operator=(Error&&) noexcept(T::error); - ~Error() noexcept(T::error); + void f() noexcept(T::error); + + Error() noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} expected-error {{type 'char'}} + Error(const Error&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} + Error(Error&&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} + Error &operator=(const Error&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} expected-error {{type 'double'}} + Error &operator=(Error&&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} + ~Error() noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} expected-error {{type 'char'}} }; + Error<char> c; // expected-note 2{{instantiation of}} struct DelayImplicit { - Error<int> e; + // FIXME: The location of this note is terrible. The instantiation was + // triggered by the uses of the functions in the decltype expressions below. + Error<int> e; // expected-note 6{{instantiation of}} }; + Error<float> *e; - // Don't instantiate the exception specification here. + // An exception specification is needed if the exception specification for a + // a defaulted special member function that calls the function is needed. + // Use in an unevaluated operand still results in the exception spec being + // needed. void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit()))); void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>())); void test3(decltype(DelayImplicit(declval<const DelayImplicit>()))); - // Any odr-use causes the exception specification to be evaluated. - struct OdrUse { // \ - expected-note {{instantiation of exception specification for 'Error'}} \ - expected-note {{instantiation of exception specification for '~Error'}} - Error<int> e; - }; - OdrUse use; // expected-note {{implicit default constructor for 'DefaultedFnExceptionSpec::OdrUse' first required here}} + // Any odr-use needs the exception specification. + void f(Error<double> *p) { + *p = *p; // expected-note {{instantiation of}} + } } namespace PR13527 { @@ -142,11 +143,11 @@ namespace PR13527 { Y &operator=(Y&&) = default; ~Y() = default; }; - Y::Y() = default; // expected-error {{definition of explicitly defaulted}} - Y::Y(const Y&) = default; // expected-error {{definition of explicitly defaulted}} - Y::Y(Y&&) = default; // expected-error {{definition of explicitly defaulted}} - Y &Y::operator=(const Y&) = default; // expected-error {{definition of explicitly defaulted}} - Y &Y::operator=(Y&&) = default; // expected-error {{definition of explicitly defaulted}} + Y::Y() noexcept = default; // expected-error {{definition of explicitly defaulted}} + Y::Y(const Y&) noexcept = default; // expected-error {{definition of explicitly defaulted}} + Y::Y(Y&&) noexcept = default; // expected-error {{definition of explicitly defaulted}} + Y &Y::operator=(const Y&) noexcept = default; // expected-error {{definition of explicitly defaulted}} + Y &Y::operator=(Y&&) noexcept = default; // expected-error {{definition of explicitly defaulted}} Y::~Y() = default; // expected-error {{definition of explicitly defaulted}} } @@ -179,7 +180,7 @@ namespace PR14577 { Outer<T>::Inner2<T>::~Inner2() = default; // expected-error {{nested name specifier 'Outer<T>::Inner2<T>::' for declaration does not refer into a class, class template or class template partial specialization}} expected-error {{only special member functions may be defaulted}} } -extern "C" { +extern "C" { // expected-note {{extern "C" language linkage specification begins here}} template<typename _Tp> // expected-error {{templates must have C++ linkage}} void PR13573(const _Tp&) = delete; } diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp index 6202bf620fe3..c10bee917ac0 100644 --- a/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -267,8 +267,11 @@ namespace PR12120 { struct A { explicit A(int); A(float); }; // expected-note {{declared here}} A a = { 0 }; // expected-error {{constructor is explicit}} - struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}} + struct B { explicit B(short); B(long); }; // expected-note 4{{candidate}} B b = { 0 }; // expected-error {{ambiguous}} + + struct C { explicit C(short); C(long); }; // expected-note 2{{candidate}} + C c = {{ 0 }}; // expected-error {{ambiguous}} } namespace PR12498 { diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp index 390047ea0752..c64511193b6e 100644 --- a/test/SemaCXX/cxx0x-initializer-references.cpp +++ b/test/SemaCXX/cxx0x-initializer-references.cpp @@ -72,10 +72,9 @@ namespace reference { } void edge_cases() { - // FIXME: very poor error message - int const &b({0}); // expected-error {{could not bind}} + int const &b({0}); // expected-error {{list-initializer for non-class type 'const int &' must not be parenthesized}} + const int (&arr)[3] ({1, 2, 3}); // expected-error {{list-initializer for non-class type 'const int (&)[3]' must not be parenthesized}} } - } namespace PR12182 { diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp index c9d5ffd19429..65b57a5584ab 100644 --- a/test/SemaCXX/cxx0x-initializer-scalars.cpp +++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -91,10 +91,23 @@ namespace integral { } void edge_cases() { - // FIXME: very poor error message - int a({0}); // expected-error {{cannot initialize}} - (void) int({0}); // expected-error {{functional-style cast}} - new int({0}); // expected-error {{cannot initialize}} + int a({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}} + (void) int({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}} + new int({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}} + + int *b({0}); // expected-error {{list-initializer for non-class type 'int *' must not be parenthesized}} + typedef int *intptr; + int *c = intptr({0}); // expected-error {{list-initializer for non-class type 'intptr' (aka 'int *') must not be parenthesized}} + } + + template<typename T> void dependent_edge_cases() { + T a({0}); + (void) T({0}); + new T({0}); + + T *b({0}); + typedef T *tptr; + T *c = tptr({0}); } void default_argument(int i = {}) { diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp index 1eeb67a3d9b3..9c617af4e95f 100644 --- a/test/SemaCXX/cxx11-ast-print.cpp +++ b/test/SemaCXX/cxx11-ast-print.cpp @@ -43,6 +43,14 @@ template <class C, C...> const char *operator"" _suffix(); // CHECK: const char *PR23120 = operator""_suffix<char32_t, 66615>(); const char *PR23120 = U"𐐷"_suffix; +// PR28885 +struct A { + A(); +}; +struct B : A { + using A::A; // CHECK: using A::A; +}; // CHECK-NEXT: }; + // CHECK: ; ; // CHECK-NOT: ; diff --git a/test/SemaCXX/cxx11-inheriting-ctors.cpp b/test/SemaCXX/cxx11-inheriting-ctors.cpp index 9c33ac05cc5f..5ce8d1aa3e0b 100644 --- a/test/SemaCXX/cxx11-inheriting-ctors.cpp +++ b/test/SemaCXX/cxx11-inheriting-ctors.cpp @@ -1,7 +1,5 @@ // RUN: %clang_cc1 -std=c++11 %s -verify -// expected-no-diagnostics - namespace PR15757 { struct S { }; @@ -56,3 +54,33 @@ namespace InvalidConstruction { template<typename T> int &f(...); int &r = f<C>(0); } + +namespace ExplicitConv { + struct B {}; // expected-note 2{{candidate}} + struct D : B { // expected-note 3{{candidate}} + using B::B; // expected-note 2{{inherited}} + }; + struct X { explicit operator B(); } x; + struct Y { explicit operator D(); } y; + + D dx(x); // expected-error {{no matching constructor}} + D dy(y); +} + +namespace NestedListInit { + struct B { B(); } b; // expected-note 5{{candidate}} + struct D : B { // expected-note 3{{candidate}} + using B::B; // expected-note 2{{inherited}} + }; + // This is a bit weird. We're allowed one pair of braces for overload + // resolution, and one more pair of braces due to [over.ics.list]/2. + B b1 = {b}; + B b2 = {{b}}; + B b3 = {{{b}}}; // expected-error {{no match}} + // This is the same, but we get one call to D's version of B::B(const B&) + // before the two permitted calls to D::D(D&&). + D d1 = {b}; + D d2 = {{b}}; + D d3 = {{{b}}}; + D d4 = {{{{b}}}}; // expected-error {{no match}} +} diff --git a/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/test/SemaCXX/cxx1y-initializer-aggregates.cpp index 9b542403def3..3d5e7726a17e 100644 --- a/test/SemaCXX/cxx1y-initializer-aggregates.cpp +++ b/test/SemaCXX/cxx1y-initializer-aggregates.cpp @@ -61,3 +61,19 @@ namespace nested_aggregate_init { }; static_assert(B(6).f() == 18, ""); } + +namespace use_self { + struct FibTree { + int n; + FibTree *l = // expected-note {{declared here}} + n > 1 ? new FibTree{n-1} : &fib0; // expected-error {{default member initializer for 'l' needed}} + FibTree *r = // expected-note {{declared here}} + n > 2 ? new FibTree{n-2} : &fib0; // expected-error {{default member initializer for 'r' needed}} + int v = l->v + r->v; + + static FibTree fib0; + }; + FibTree FibTree::fib0{0, nullptr, nullptr, 1}; + + int fib(int n) { return FibTree{n}.v; } +} diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index e2fbdfd69954..76f1bb9905b9 100644 --- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -26,10 +26,10 @@ namespace out_of_line { template<typename T, typename T0> static CONST T right = T(100); template<typename T> static CONST T right<T,int> = T(5); }; - template<> CONST int B0::right<int,int> = 7; - template CONST int B0::right<int,int>; - template<> CONST int B0::right<int,float>; - template CONST int B0::right<int,float>; + template<> CONST int B0::right<int,int> = 7; // expected-note {{previous}} + template CONST int B0::right<int,int>; // expected-warning {{has no effect}} + template<> CONST int B0::right<int,float>; // expected-note {{previous}} + template CONST int B0::right<int,float>; // expected-warning {{has no effect}} class B1 { template<typename T, typename T0> static CONST T right; diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index 496ae888732f..ec3e2b6f63d1 100644 --- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -264,9 +264,9 @@ namespace explicit_specialization { template<typename T> T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}} - template<> int pi0<int> = 10; - template int pi0<int>; - template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} + template<> int pi0<int> = 10; // expected-note 2{{previous template specialization is here}} + template int pi0<int>; // expected-warning {{has no effect}} + template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} expected-warning {{has no effect}} template<typename T1, typename T2> CONST int pi2 = 1; diff --git a/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/test/SemaCXX/cxx1z-constexpr-lambdas.cpp new file mode 100644 index 000000000000..90a07665cbf7 --- /dev/null +++ b/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s +// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s +// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER + + +namespace test_lambda_is_literal { +#ifdef CPP14_AND_EARLIER +//expected-error@+4{{not a literal type}} +//expected-note@+2{{not an aggregate and has no constexpr constructors}} +#endif +auto L = [] { }; +constexpr int foo(decltype(L) l) { return 0; } + +} + +#ifndef CPP14_AND_EARLIER +namespace test_constexpr_checking { + +namespace ns1 { + struct NonLit { ~NonLit(); }; //expected-note{{not literal}} + auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}} +} // end ns1 + +namespace ns2 { + auto L = [](int I) constexpr { asm("non-constexpr"); }; //expected-error{{not allowed in constexpr function}} +} // end ns1 + +} // end ns test_constexpr_checking + +namespace test_constexpr_call { + +namespace ns1 { + auto L = [](int I) { return I; }; + static_assert(L(3) == 3); +} // end ns1 +namespace ns2 { + auto L = [](auto a) { return a; }; + static_assert(L(3) == 3); + static_assert(L(3.14) == 3.14); +} +namespace ns3 { + auto L = [](auto a) { asm("non-constexpr"); return a; }; //expected-note{{declared here}} + constexpr int I = //expected-error{{must be initialized by a constant expression}} + L(3); //expected-note{{non-constexpr function}} +} + +} // end ns test_constexpr_call + +namespace test_captureless_lambda { +void f() { + const char c = 'c'; + auto L = [] { return c; }; + constexpr char C = L(); +} + +void f(char c) { //expected-note{{declared here}} + auto L = [] { return c; }; //expected-error{{cannot be implicitly captured}} expected-note{{lambda expression begins here}} + int I = L(); +} + +} +#endif // ndef CPP14_AND_EARLIER diff --git a/test/SemaCXX/cxx1z-copy-omission.cpp b/test/SemaCXX/cxx1z-copy-omission.cpp new file mode 100644 index 000000000000..e2b8fd796174 --- /dev/null +++ b/test/SemaCXX/cxx1z-copy-omission.cpp @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +struct Noncopyable { + Noncopyable(); + Noncopyable(const Noncopyable &) = delete; // expected-note 1+{{deleted}} + virtual ~Noncopyable(); +}; +struct Derived : Noncopyable {}; +struct NoncopyableAggr { + Noncopyable nc; +}; +struct Indestructible { + Indestructible(); + ~Indestructible() = delete; // expected-note 1+{{deleted}} +}; +struct Incomplete; // expected-note 1+{{declar}} + +Noncopyable make(int kind = 0) { + switch (kind) { + case 0: return {}; + case 1: return Noncopyable(); + case 2: return Noncopyable{}; + case 3: return make(); + } + __builtin_unreachable(); +} + +Indestructible make_indestructible(); +Incomplete make_incomplete(); // expected-note 1+{{here}} + +void take(Noncopyable nc) {} + +Noncopyable nrvo() { + Noncopyable nrvo; + return nrvo; // expected-error {{deleted constructor}} +} + +Noncopyable nc1 = make(); +Noncopyable nc2 = Noncopyable(); +Noncopyable nc3 = Derived(); // expected-error {{deleted constructor}} + +NoncopyableAggr nca1 = NoncopyableAggr{}; +NoncopyableAggr nca2 = NoncopyableAggr{{}}; +NoncopyableAggr nca3 = NoncopyableAggr{NoncopyableAggr{Noncopyable()}}; + +void test_expressions(bool b) { + auto lambda = [a = make()] {}; + + take({}); + take(Noncopyable()); + take(Noncopyable{}); + take(make()); + + Noncopyable &&dc1 = dynamic_cast<Noncopyable&&>(Noncopyable()); + Noncopyable &&dc2 = dynamic_cast<Noncopyable&&>(nc1); + Noncopyable &&dc3 = dynamic_cast<Noncopyable&&>(Derived()); + + Noncopyable sc1 = static_cast<Noncopyable>(Noncopyable()); + Noncopyable sc2 = static_cast<Noncopyable>(nc1); // expected-error {{deleted}} + Noncopyable sc3 = static_cast<Noncopyable&&>(Noncopyable()); // expected-error {{deleted}} + Noncopyable sc4 = static_cast<Noncopyable>(static_cast<Noncopyable&&>(Noncopyable())); // expected-error {{deleted}} + + Noncopyable cc1 = (Noncopyable)Noncopyable(); + Noncopyable cc2 = (Noncopyable)Derived(); // expected-error {{deleted}} + + Noncopyable fc1 = Noncopyable(Noncopyable()); + Noncopyable fc2 = Noncopyable(Derived()); // expected-error {{deleted}} + + // We must check for a complete type for every materialized temporary. (Note + // that in the special case of the top level of a decltype, no temporary is + // materialized.) + make_incomplete(); // expected-error {{incomplete}} + make_incomplete().a; // expected-error {{incomplete}} + make_incomplete().*(int Incomplete::*)nullptr; // expected-error {{incomplete}} + dynamic_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}} + const_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}} + + sizeof(Indestructible{}); // expected-error {{deleted}} + sizeof(make_indestructible()); // expected-error {{deleted}} + sizeof(make_incomplete()); // expected-error {{incomplete}} + typeid(Indestructible{}); // expected-error {{deleted}} + typeid(make_indestructible()); // expected-error {{deleted}} + typeid(make_incomplete()); // expected-error {{incomplete}} + + // FIXME: The first two cases here are now also valid in C++17 onwards. + using I = decltype(Indestructible()); // expected-error {{deleted}} + using I = decltype(Indestructible{}); // expected-error {{deleted}} + using I = decltype(make_indestructible()); + using J = decltype(make_incomplete()); + + Noncopyable cond1 = b ? Noncopyable() : make(); + Noncopyable cond2 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}} + Noncopyable cond3 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}} + Noncopyable cond4 = b ? Noncopyable() : nc1; // expected-error {{deleted}} + Noncopyable cond5 = b ? nc1 : Noncopyable(); // expected-error {{deleted}} + // Could convert both to an xvalue of type Noncopyable here, but we're not + // permitted to consider that. + Noncopyable &&cond6 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}} + Noncopyable &&cond7 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}} + // Could convert both to a const lvalue of type Noncopyable here, but we're + // not permitted to consider that, either. + const Noncopyable cnc; + const Noncopyable &cond8 = b ? cnc : Derived(); // expected-error {{incompatible}} + const Noncopyable &cond9 = b ? Derived() : cnc; // expected-error {{incompatible}} + + extern const volatile Noncopyable make_cv(); + Noncopyable cv_difference1 = make_cv(); + const volatile Noncopyable cv_difference2 = make(); +} + +template<typename T> struct ConversionFunction { operator T(); }; +Noncopyable cf1 = ConversionFunction<Noncopyable>(); +Noncopyable cf2 = ConversionFunction<Noncopyable&&>(); // expected-error {{deleted}} +Noncopyable cf3 = ConversionFunction<const volatile Noncopyable>(); +const volatile Noncopyable cf4 = ConversionFunction<Noncopyable>(); +Noncopyable cf5 = ConversionFunction<Derived>(); // expected-error {{deleted}} + +struct AsMember { + Noncopyable member; + AsMember() : member(make()) {} +}; +// FIXME: DR (no number yet): we still get a copy for base or delegating construction. +struct AsBase : Noncopyable { + AsBase() : Noncopyable(make()) {} // expected-error {{deleted}} +}; +struct AsDelegating final { + AsDelegating(const AsDelegating &) = delete; // expected-note {{deleted}} + static AsDelegating make(int); + + // The base constructor version of this is problematic; the complete object + // version would be OK. Perhaps we could allow copy omission here for final + // classes? + AsDelegating(int n) : AsDelegating(make(n)) {} // expected-error {{deleted}} +}; diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp new file mode 100644 index 000000000000..735a9e1dfee0 --- /dev/null +++ b/test/SemaCXX/cxx1z-decomposition.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +void use_from_own_init() { + auto [a] = a; // expected-error {{binding 'a' cannot appear in the initializer of its own decomposition declaration}} +} + +// As a Clang extension, _Complex can be decomposed. +float decompose_complex(_Complex float cf) { + static _Complex float scf; + auto &[sre, sim] = scf; + // ok, this is references initialized by constant expressions all the way down + static_assert(&sre == &__real scf); + static_assert(&sim == &__imag scf); + + auto [re, im] = cf; + return re*re + im*im; +} + +// As a Clang extension, vector types can be decomposed. +typedef float vf3 __attribute__((ext_vector_type(3))); +float decompose_vector(vf3 v) { + auto [x, y, z] = v; + auto *p = &x; // expected-error {{address of vector element requested}} + return x + y + z; +} + +struct S { int a, b; }; +constexpr int f(S s) { + auto &[a, b] = s; + return a * 10 + b; +} +static_assert(f({1, 2}) == 12); + +constexpr bool g(S &&s) { + auto &[a, b] = s; + return &a == &s.a && &b == &s.b && &a != &b; +} +static_assert(g({1, 2})); + +void enclosing() { + struct S { int a; }; + auto [n] = S(); // expected-note 2{{'n' declared here}} + + struct Q { int f() { return n; } }; // expected-error {{reference to local binding 'n' declared in enclosing function}} + // FIXME: This is probably supposed to be valid, but we do not have clear rules on how it's supposed to work. + (void) [&] { return n; }; // expected-error {{reference to local binding 'n' declared in enclosing function}} + (void) [n] {}; // expected-error {{'n' in capture list does not name a variable}} +} + +void bitfield() { + struct { int a : 3, : 4, b : 5; } a; + auto &[x, y] = a; + auto &[p, q, r] = a; // expected-error {{decomposes into 2 elements, but 3 names were provided}} +} + +void for_range() { + int x = 1; + for (auto[a, b] : x) { // expected-error {{invalid range expression of type 'int'; no viable 'begin' function available}} + a++; + } + + int y[5]; + for (auto[c] : y) { // expected-error {{cannot decompose non-class, non-array type 'int'}} + c++; + } +} + +// FIXME: by-value array copies diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp new file mode 100644 index 000000000000..a3f710970456 --- /dev/null +++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -0,0 +1,167 @@ +// RUN: %clang_cc1 -std=c++14 -verify -fexceptions -fcxx-exceptions %s +// RUN: %clang_cc1 -std=c++1z -verify -fexceptions -fcxx-exceptions %s -Wno-dynamic-exception-spec + +#if __cplusplus > 201402L + +template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-note {{previous}} +template<typename T> void redecl1() noexcept(noexcept(T())); // ok, same type +template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-error {{redefinition}} + +template<bool A, bool B> void redecl2() noexcept(A); // expected-note {{previous}} +template<bool A, bool B> void redecl2() noexcept(B); // expected-error {{conflicting types}} + +// These have the same canonical type, but are still different. +template<typename A, typename B> void redecl3() throw(A); // expected-note {{previous}} +template<typename A, typename B> void redecl3() throw(B); // expected-error {{does not match previous}} + +typedef int I; +template<bool B> void redecl4(I) noexcept(B); +template<bool B> void redecl4(I) noexcept(B); // expected-note {{failed template argument deduction}} + +void (*init_with_exact_type_a)(int) noexcept = redecl4<true>; +void (*init_with_mismatched_type_a)(int) = redecl4<true>; +auto deduce_auto_from_noexcept_function_ptr_a = redecl4<true>; +using DeducedType_a = decltype(deduce_auto_from_noexcept_function_ptr_a); +using DeducedType_a = void (*)(int) noexcept; + +void (*init_with_exact_type_b)(int) = redecl4<false>; +void (*init_with_mismatched_type_b)(int) noexcept = redecl4<false>; // expected-error {{does not match required type}} +auto deduce_auto_from_noexcept_function_ptr_b = redecl4<false>; +using DeducedType_b = decltype(deduce_auto_from_noexcept_function_ptr_b); +using DeducedType_b = void (*)(int); + +static_assert(noexcept(init_with_exact_type_a(0))); +static_assert(noexcept((+init_with_exact_type_a)(0))); +static_assert(!noexcept(init_with_exact_type_b(0))); +static_assert(!noexcept((+init_with_exact_type_b)(0))); + +// Don't look through casts, use the direct type of the expression. +// FIXME: static_cast here would be reasonable, but is not currently permitted. +static_assert(noexcept(static_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0))); // expected-error {{is not allowed}} +static_assert(noexcept(reinterpret_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0))); +static_assert(!noexcept(static_cast<decltype(init_with_exact_type_b)>(init_with_exact_type_a)(0))); + +template<bool B> auto get_fn() noexcept -> void (*)() noexcept(B) {} +static_assert(noexcept(get_fn<true>()())); +static_assert(!noexcept(get_fn<false>()())); + +namespace DependentDefaultCtorExceptionSpec { + template<typename> struct T { static const bool value = true; }; + + template<class A> struct map { + typedef A a; + map() noexcept(T<a>::value) {} + }; + + template<class B> struct multimap { + typedef B b; + multimap() noexcept(T<b>::value) {} + }; + + // Don't crash here. + struct A { multimap<int> Map; } a; + + static_assert(noexcept(A())); +} + +#endif + +namespace CompatWarning { + struct X; + + // These cases don't change. + void f0(void p() throw(int)); + auto f0() -> void (*)() noexcept(false); + + // These cases take an ABI break in C++17 because their parameter / return types change. + void f1(void p() noexcept); + void f2(void (*p)() noexcept(true)); + void f3(void (&p)() throw()); + void f4(void (X::*p)() throw()); + auto f5() -> void (*)() throw(); + auto f6() -> void (&)() throw(); + auto f7() -> void (X::*)() throw(); +#if __cplusplus <= 201402L + // expected-warning@-8 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}} + // expected-warning@-8 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}} + // expected-warning@-8 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}} + // expected-warning@-8 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}} + // expected-warning@-8 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}} + // expected-warning@-8 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}} + // expected-warning@-8 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}} +#endif + + // An instantiation-dependent exception specification needs to be mangled in + // all language modes, since it participates in SFINAE. + template<typename T> void g(void() throw(T)); // expected-note {{substitution failure}} + template<typename T> void g(...) = delete; // expected-note {{deleted}} + void test_g() { g<void>(nullptr); } // expected-error {{deleted}} + + // An instantiation-dependent exception specification needs to be mangled in + // all language modes, since it participates in SFINAE. + template<typename T> void h(void() noexcept(T())); // expected-note {{substitution failure}} + template<typename T> void h(...) = delete; // expected-note {{deleted}} + void test_h() { h<void>(nullptr); } // expected-error {{deleted}} +} + +namespace ImplicitExceptionSpec { + struct S { + ~S(); + void f(const S &s = S()); + }; + S::~S() {} +} + +namespace Builtins { + // Pick two functions that ought to have the same noexceptness. + extern "C" int strcmp(const char *, const char *); + extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept; + + // Check we recognized both as builtins. + typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)]; + typedef int arr[3]; +} + +namespace ExplicitInstantiation { + template<typename T> void f() noexcept {} + template<typename T> struct X { void f() noexcept {} }; + template void f<int>(); + template void X<int>::f(); +} + +namespace ConversionFunction { + struct A { template<typename T> operator T() noexcept; }; + int a = A().operator int(); +} + +using size_t = decltype(sizeof(0)); + +namespace OperatorDelete { + struct W {}; + struct X {}; + struct Y {}; + struct Z {}; + template<bool N, bool D> struct T {}; +} +void *operator new(size_t, OperatorDelete::W) noexcept(false); +void operator delete(void*, OperatorDelete::W) noexcept(false) = delete; // expected-note {{here}} +void *operator new(size_t, OperatorDelete::X) noexcept(false); +void operator delete(void*, OperatorDelete::X) noexcept(true) = delete; // expected-note {{here}} +void *operator new(size_t, OperatorDelete::Y) noexcept(true); +void operator delete(void*, OperatorDelete::Y) noexcept(false) = delete; // expected-note {{here}} +void *operator new(size_t, OperatorDelete::Z) noexcept(true); +void operator delete(void*, OperatorDelete::Z) noexcept(true) = delete; // expected-note {{here}} +template<bool N, bool D> void *operator new(size_t, OperatorDelete::T<N, D>) noexcept(N); +template<bool N, bool D> void operator delete(void*, OperatorDelete::T<N, D>) noexcept(D) = delete; // expected-note 4{{here}} +namespace OperatorDelete { + struct A { A(); }; + A *w = new (W{}) A; // expected-error {{deleted function}} + A *x = new (X{}) A; // expected-error {{deleted function}} + A *y = new (Y{}) A; // expected-error {{deleted function}} + A *z = new (Z{}) A; // expected-error {{deleted function}} + + A *t00 = new (T<false, false>{}) A; // expected-error {{deleted function}} + A *t01 = new (T<false, true>{}) A; // expected-error {{deleted function}} + A *t10 = new (T<true, false>{}) A; // expected-error {{deleted function}} + A *t11 = new (T<true, true>{}) A; // expected-error {{deleted function}} +} diff --git a/test/SemaCXX/cxx1z-user-defined-literals.cpp b/test/SemaCXX/cxx1z-user-defined-literals.cpp new file mode 100644 index 000000000000..978fd2fbc4b2 --- /dev/null +++ b/test/SemaCXX/cxx1z-user-defined-literals.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++1z %s -include %s -verify + +#ifndef INCLUDED +#define INCLUDED + +#pragma clang system_header +namespace std { + using size_t = decltype(sizeof(0)); + + struct string_view {}; + string_view operator""sv(const char*, size_t); +} + +#else + +using namespace std; +string_view s = "foo"sv; +const char* p = "bar"sv; // expected-error {{no viable conversion}} +char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}} + +#endif diff --git a/test/SemaCXX/cxx98-compat-flags.cpp b/test/SemaCXX/cxx98-compat-flags.cpp index f90ad345e975..62d687c49cf7 100644 --- a/test/SemaCXX/cxx98-compat-flags.cpp +++ b/test/SemaCXX/cxx98-compat-flags.cpp @@ -16,7 +16,7 @@ namespace CopyCtorIssues { Private(const Private&); // expected-note {{declared private here}} }; struct NoViable { - NoViable(); + NoViable(); // expected-note {{not viable}} NoViable(NoViable&); // expected-note {{not viable}} }; struct Ambiguous { diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp index 38bc341e83ce..c72c44ad5feb 100644 --- a/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -21,10 +21,6 @@ enum Enum { Enum_value, // expected-warning {{commas at the end of enumerator lists are incompatible with C++98}} }; -template<typename T> struct InstantiationAfterSpecialization {}; -template<> struct InstantiationAfterSpecialization<int> {}; // expected-note {{here}} -template struct InstantiationAfterSpecialization<int>; // expected-warning {{explicit instantiation of 'InstantiationAfterSpecialization<int>' that occurs after an explicit specialization is incompatible with C++98}} - void *dlsym(); void (*FnPtr)() = (void(*)())dlsym(); // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}} void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}} @@ -59,7 +55,7 @@ namespace CopyCtorIssues { Private(const Private&); // expected-note {{declared private here}} }; struct NoViable { - NoViable(); + NoViable(); // expected-note {{not viable}} NoViable(NoViable&); // expected-note {{not viable}} }; struct Ambiguous { diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 25a086d9bcd3..4a9baf5100d6 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -361,7 +361,7 @@ template<typename T> T var = T(10); // diagnosed the primary template. template<typename T> T* var<T*> = new T(); template<> int var<int> = 10; -template int var<int>; +template char var<char>; float fvar = var<float>; class A { @@ -391,7 +391,7 @@ template<typename T> T B::v = T(); template<typename T> T* B::v<T*> = new T(); template<> int B::v<int> = 10; -template int B::v<int>; +template char B::v<char>; float fsvar = B::v<float>; #ifdef CXX14COMPAT diff --git a/test/SemaCXX/default-arg-closures.cpp b/test/SemaCXX/default-arg-closures.cpp new file mode 100644 index 000000000000..e076cc05cd20 --- /dev/null +++ b/test/SemaCXX/default-arg-closures.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fms-extensions -verify %s -std=c++11 + +// The MS ABI has a few ways to generate constructor closures, which require +// instantiating and checking the semantics of default arguments. Make sure we +// do that right. + +// FIXME: Don't diagnose this issue twice. +template <typename T> +struct DependentDefaultCtorArg { // expected-note {{in instantiation of default function argument}} + // expected-error@+1 2 {{type 'int' cannot be used prior to '::' because it has no members}} + DependentDefaultCtorArg(int n = T::error); +}; +struct +__declspec(dllexport) // expected-note {{due to 'ExportDefaultCtorClosure' being dllexported}} +ExportDefaultCtorClosure // expected-note {{implicit default constructor for 'ExportDefaultCtorClosure' first required here}} +: DependentDefaultCtorArg<int> // expected-note {{in instantiation of template class}} +{}; + +template <typename T> +struct DependentDefaultCopyArg { + DependentDefaultCopyArg() {} + // expected-error@+1 {{type 'int' cannot be used prior to '::' because it has no members}} + DependentDefaultCopyArg(const DependentDefaultCopyArg &o, int n = T::member) {} +}; + +struct HasMember { + enum { member = 0 }; +}; +void UseDependentArg() { throw DependentDefaultCopyArg<HasMember>(); } + +void ErrorInDependentArg() { + throw DependentDefaultCopyArg<int>(); // expected-note {{required here}} +} + +struct HasCleanup { + ~HasCleanup(); +}; + +struct Default { + Default(const Default &o, int d = (HasCleanup(), 42)); +}; + +void f(const Default &d) { + throw d; +} diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp index 4ce058968742..0fd275e2cec6 100644 --- a/test/SemaCXX/deprecated.cpp +++ b/test/SemaCXX/deprecated.cpp @@ -7,13 +7,17 @@ #include "Inputs/register.h" -void f() throw(); -void g() throw(int); -void h() throw(...); -#if __cplusplus >= 201103L +void g() throw(); +void h() throw(int); +void i() throw(...); +#if __cplusplus > 201402L // expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept' instead}} -// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}} -// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}} +// expected-error@-4 {{ISO C++1z does not allow dynamic exception specifications}} expected-note@-4 {{use 'noexcept(false)' instead}} +// expected-error@-4 {{ISO C++1z does not allow dynamic exception specifications}} expected-note@-4 {{use 'noexcept(false)' instead}} +#elif __cplusplus >= 201103L +// expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept' instead}} +// expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept(false)' instead}} +// expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept(false)' instead}} #endif void stuff() { diff --git a/test/SemaCXX/derived-to-base-ambig.cpp b/test/SemaCXX/derived-to-base-ambig.cpp index 93bd3619ccdf..5d1d56b76614 100644 --- a/test/SemaCXX/derived-to-base-ambig.cpp +++ b/test/SemaCXX/derived-to-base-ambig.cpp @@ -6,7 +6,7 @@ class D : public B, public C { }; void f(D* d) { A* a; - a = d; // expected-error{{ambiguous conversion from derived class 'D' to base class 'A':}} expected-error{{assigning to 'A *' from incompatible type 'D *'}} + a = d; // expected-error{{ambiguous conversion from derived class 'D' to base class 'A':}} } class Object2 { }; @@ -20,7 +20,7 @@ class F2 : public E2, public A2 { }; // expected-warning{{direct base 'A2' is in void g(E2* e2, F2* f2) { Object2* o2; o2 = e2; - o2 = f2; // expected-error{{ambiguous conversion from derived class 'F2' to base class 'Object2':}} expected-error{{assigning to 'Object2 *' from incompatible type 'F2 *'}} + o2 = f2; // expected-error{{ambiguous conversion from derived class 'F2' to base class 'Object2':}} } // Test that ambiguous/inaccessibility checking does not trigger too diff --git a/test/SemaCXX/designated-initializers.cpp b/test/SemaCXX/designated-initializers.cpp new file mode 100644 index 000000000000..e5b5f3c9cce2 --- /dev/null +++ b/test/SemaCXX/designated-initializers.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Winitializer-overrides %s + +template <typename T> struct Foo { + struct SubFoo { + int bar1; + int bar2; + }; + + static void Test() { SubFoo sf = {.bar1 = 10, .bar2 = 20}; } // Expected no warning +}; + +void foo() { + Foo<int>::Test(); + Foo<bool>::Test(); + Foo<float>::Test(); +} + +template <typename T> struct Bar { + struct SubFoo { + int bar1; + int bar2; + }; + + static void Test() { SubFoo sf = {.bar1 = 10, // expected-note 2 {{previous initialization is here}} + .bar1 = 20}; } // expected-warning 2 {{initializer overrides prior initialization of this subobject}} +}; + +void bar() { + Bar<int>::Test(); // expected-note {{in instantiation of member function 'Bar<int>::Test' requested here}} + Bar<bool>::Test(); // expected-note {{in instantiation of member function 'Bar<bool>::Test' requested here}} +} diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp index 81c5cb4eac59..3701dd7ba630 100644 --- a/test/SemaCXX/elaborated-type-specifier.cpp +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -52,3 +52,12 @@ namespace test5 { } }; } + +namespace test6 { +struct C { + template <typename> friend struct A; // expected-note {{'A' declared here}} +}; +struct B { + struct A *p; // expected-error {{implicit declaration introduced by elaborated type conflicts with a template of the same name}} +}; +} diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp index 81308136c480..0f8fc9b2652a 100644 --- a/test/SemaCXX/enable_if.cpp +++ b/test/SemaCXX/enable_if.cpp @@ -440,3 +440,27 @@ void testFoo() { foo(1, 0, m, 3); // expected-error{{no matching}} } } + +// Tests that we emit errors at the point of the method call, rather than the +// beginning of the expression that happens to be a member call. +namespace member_loc { + struct Foo { void bar() __attribute__((enable_if(0, ""))); }; // expected-note{{disabled}} + void testFoo() { + Foo() + .bar(); // expected-error{{no matching member function}} + } +} + +// Prior bug: we wouldn't properly convert conditions to bools when +// instantiating templates in some cases. +namespace template_instantiation { +template <typename T> +struct Foo { + void bar(int a) __attribute__((enable_if(a, ""))); // expected-note{{disabled}} +}; + +void runFoo() { + Foo<double>().bar(0); // expected-error{{no matching}} + Foo<double>().bar(1); +} +} diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 51bb90e8bbf9..d965d14747ae 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify -fcxx-exceptions %s // // Tests for "expression traits" intrinsics such as __is_lvalue_expr. diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp index 4f27f4df6c90..1f64ba609b16 100644 --- a/test/SemaCXX/friend.cpp +++ b/test/SemaCXX/friend.cpp @@ -379,3 +379,12 @@ namespace tag_redecl { X *q = p; } } + +namespace default_arg { + void f(); + void f(void*); // expected-note {{previous}} + struct X { + friend void f(int a, int b = 0) {} + friend void f(void *p = 0) {} // expected-error {{must be the only}} + }; +} diff --git a/test/SemaCXX/friend2.cpp b/test/SemaCXX/friend2.cpp new file mode 100644 index 000000000000..347af0d61b1b --- /dev/null +++ b/test/SemaCXX/friend2.cpp @@ -0,0 +1,172 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +// If a friend function is defined in several non-template classes, +// it is an error. + +void func1(int); +struct C1a { + friend void func1(int) {} // expected-note{{previous definition is here}} +}; +struct C1b { + friend void func1(int) {} // expected-error{{redefinition of 'func1'}} +}; + + +// If a friend function is defined in both non-template and template +// classes it is an error only if the template is instantiated. + +void func2(int); +struct C2a { + friend void func2(int) {} +}; +template<typename T> struct C2b { + friend void func2(int) {} +}; + +void func3(int); +struct C3a { + friend void func3(int) {} // expected-note{{previous definition is here}} +}; +template<typename T> struct C3b { + friend void func3(int) {} // expected-error{{redefinition of 'func3'}} +}; +C3b<long> c3; // expected-note{{in instantiation of template class 'C3b<long>' requested here}} + + +// If a friend function is defined in several template classes it is an error +// only if several templates are instantiated. + +void func4(int); +template<typename T> struct C4a { + friend void func4(int) {} +}; +template<typename T> struct C4b { + friend void func4(int) {} +}; + + +void func5(int); +template<typename T> struct C5a { + friend void func5(int) {} +}; +template<typename T> struct C5b { + friend void func5(int) {} +}; +C5a<long> c5a; + +void func6(int); +template<typename T> struct C6a { + friend void func6(int) {} // expected-note{{previous definition is here}} +}; +template<typename T> struct C6b { + friend void func6(int) {} // expected-error{{redefinition of 'func6'}} +}; +C6a<long> c6a; +C6b<int*> c6b; // expected-note{{in instantiation of template class 'C6b<int *>' requested here}} + +void func7(int); +template<typename T> struct C7 { + friend void func7(int) {} // expected-error{{redefinition of 'func7'}} + // expected-note@-1{{previous definition is here}} +}; +C7<long> c7a; +C7<int*> c7b; // expected-note{{in instantiation of template class 'C7<int *>' requested here}} + + +// Even if clases are not instantiated and hence friend functions defined in them are not +// available, their declarations can be checked. + +void func8(int); // expected-note{{previous declaration is here}} +template<typename T> struct C8a { + friend long func8(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} +}; + +void func9(int); // expected-note{{previous declaration is here}} +template<typename T> struct C9a { + friend int func9(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} +}; + +void func10(int); // expected-note{{previous declaration is here}} +template<typename T> struct C10a { + friend int func10(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} +}; + +void func_11(); // expected-note{{previous declaration is here}} +template<typename T> class C11 { + friend int func_11(); // expected-error{{functions that differ only in their return type cannot be overloaded}} +}; + +void func_12(int x); // expected-note{{previous declaration is here}} +template<typename T> class C12 { + friend void func_12(int x = 0); // expected-error{{friend declaration specifying a default argument must be the only declaration}} +}; + + +namespace pr22307 { + +struct t { + friend int leak(t); +}; + +template<typename v> +struct m { + friend int leak(t) { return sizeof(v); } // expected-error{{redefinition of 'leak'}} expected-note{{previous definition is here}} +}; + +template struct m<char>; +template struct m<short>; // expected-note{{in instantiation of template class 'pr22307::m<short>' requested here}} + +int main() { + leak(t()); +} + +} + +namespace pr17923 { + +void f(unsigned long long); + +template<typename T> struct X { + friend void f(unsigned long long) { + T t; + } +}; + +int main() { f(1234); } + +} + +namespace pr17923a { + +int get(); + +template< int value > +class set { + friend int get() + { return value; } // return 0; is OK +}; + +template class set< 5 >; + +int main() { + get(); +} + +} + +namespace pr8035 { + +void Function(); + +int main(int argc, char* argv[]) { + Function(); +} + +template <typename T> +struct Test { + friend void Function() { } +}; + +template class Test<int>; + +} diff --git a/test/SemaCXX/function-redecl-2.cpp b/test/SemaCXX/function-redecl-2.cpp new file mode 100644 index 000000000000..9ceeb205be88 --- /dev/null +++ b/test/SemaCXX/function-redecl-2.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace redecl_in_templ { +template<typename T> void redecl_in_templ() { + extern void func_1(); // expected-note {{previous declaration is here}} + extern int func_1(); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} + +void g(); +constexpr void (*p)() = g; + +template<bool> struct X {}; +template<> struct X<true> { typedef int type; }; + +template<typename T> void f() { + extern void g(); + X<&g == p>::type n; +} +} diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp index ff3d685d912e..12871b8ce707 100644 --- a/test/SemaCXX/implicit-exception-spec.cpp +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -16,31 +16,31 @@ namespace InClassInitializers { // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept()) // is false. bool ThrowSomething() noexcept(false); - struct ConstExpr { - bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{cannot use defaulted default constructor of 'ConstExpr' within the class outside of member functions}} + struct ConstExpr { // expected-error {{default member initializer for 'b' needed}} + bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-note {{declared here}} // expected-note@-1 {{implicit default constructor for 'InClassInitializers::ConstExpr' first required here}} }; // Much more obviously broken: we can't parse the initializer without already // knowing whether it produces a noexcept expression. - struct TemplateArg { - int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{cannot use defaulted default constructor of 'TemplateArg' within the class outside of member functions}} + struct TemplateArg { // expected-error {{default member initializer for 'n' needed}} + int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-note {{declared here}} // expected-note@-1 {{implicit default constructor for 'InClassInitializers::TemplateArg' first required here}} }; // And within a nested class. struct Nested { // expected-note {{implicit default constructor for 'InClassInitializers::Nested::Inner' first required here}} - struct Inner { - // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested' outside of member functions}} - int n = ExceptionIf<noexcept(Nested())>::f(); // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}} + struct Inner { // expected-error {{default member initializer for 'n' needed}} + int n = // expected-note {{declared here}} + ExceptionIf<noexcept(Nested())>::f(); // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}} } inner; }; struct Nested2 { // expected-error {{implicit default constructor for 'InClassInitializers::Nested2' must explicitly initialize the member 'inner' which does not have a default constructor}} struct Inner; int n = Inner().n; // expected-note {{implicit default constructor for 'InClassInitializers::Nested2::Inner' first required here}} - struct Inner { // expected-note {{declared here}} - // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested2' outside of member functions}} + struct Inner { // expected-error {{initializer for 'n' needed}} expected-note {{declared here}} + // expected-note@+1 {{declared here}} int n = ExceptionIf<noexcept(Nested2())>::f(); // expected-note@-1 {{implicit default constructor for 'InClassInitializers::Nested2' first required here}} } inner; // expected-note {{member is declared here}} diff --git a/test/SemaCXX/instantiate-template-fatal-error.cpp b/test/SemaCXX/instantiate-template-fatal-error.cpp new file mode 100644 index 000000000000..9c8916e77bb0 --- /dev/null +++ b/test/SemaCXX/instantiate-template-fatal-error.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s + +#pragma clang diagnostic fatal "-Wall" +#pragma clang diagnostic fatal "-Wold-style-cast" + +template <class T> bool foo0(const long long *a, T* b) { + return a == (const long long*)b; // expected-error {{use of old-style cast}} +} + +template<class T> +struct S1 { +}; + +template<class T> +struct S2 : S1<T> { + bool m1(const long long *a, T *b) const { return foo0(a, b); } +}; + +bool foo1(const long long *a, int *b) { + S2<int> s2; + return s2.m1(a, b); +} diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 5fffe4111783..e0ab15dc6327 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -95,6 +95,39 @@ namespace ImplicitCapture { } } +namespace SpecialMembers { + void f() { + auto a = []{}; // expected-note 2{{here}} expected-note 2{{candidate}} + decltype(a) b; // expected-error {{no matching constructor}} + decltype(a) c = a; + decltype(a) d = static_cast<decltype(a)&&>(a); + a = a; // expected-error {{copy assignment operator is implicitly deleted}} + a = static_cast<decltype(a)&&>(a); // expected-error {{copy assignment operator is implicitly deleted}} + } + struct P { + P(const P&) = delete; // expected-note {{deleted here}} + }; + struct Q { + ~Q() = delete; // expected-note {{deleted here}} + }; + struct R { + R(const R&) = default; + R(R&&) = delete; + R &operator=(const R&) = delete; + R &operator=(R&&) = delete; + }; + void g(P &p, Q &q, R &r) { + auto pp = [p]{}; // expected-error {{deleted constructor}} + auto qq = [q]{}; // expected-error {{deleted function}} expected-note {{because}} + + auto a = [r]{}; // expected-note 2{{here}} + decltype(a) b = a; + decltype(a) c = static_cast<decltype(a)&&>(a); // ok, copies R + a = a; // expected-error {{copy assignment operator is implicitly deleted}} + a = static_cast<decltype(a)&&>(a); // expected-error {{copy assignment operator is implicitly deleted}} + } +} + namespace PR12031 { struct X { template<typename T> @@ -525,3 +558,18 @@ int func() { decltype(a)::D b; } } + +namespace PR30566 { +int name1; // expected-note {{'name1' declared here}} + +struct S1 { + template<class T> + S1(T t) { s = sizeof(t); } + int s; +}; + +void foo1() { + auto s0 = S1{[name=]() {}}; // expected-error 2 {{expected expression}} + auto s1 = S1{[name=name]() {}}; // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}} +} +} diff --git a/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp b/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp new file mode 100644 index 000000000000..53b6a3b2c42d --- /dev/null +++ b/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp @@ -0,0 +1,67 @@ +// This is a test for a hack in Clang that works around a problem introduced by +// DR583: it's no longer possible to compare a pointer against nullptr_t, but +// we still want to permit those comparisons within less<> and friends. + +// RUN: %clang_cc1 -verify %s -std=c++14 + +namespace std { + template<typename T = void> struct less {}; + template<typename T = void> struct less_equal {}; + template<typename T = void> struct greater {}; + template<typename T = void> struct greater_equal {}; + + template<> struct less<> { + template <class T1, class T2> + auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) + -> decltype(t < u) { + return t < u; + } + }; + + template<> struct less_equal<> { + template <class T1, class T2> + auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t <= u)) + -> decltype(t <= u) { + return t <= u; + } + }; + + template<> struct greater<> { + template <class T1, class T2> + auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t > u)) + -> decltype(t > u) { + return t > u; + } + }; + + template<> struct greater_equal<> { + template <class T1, class T2> + auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t >= u)) + -> decltype(t >= u) { + return t >= u; + } + }; + + template<typename = void> struct unrelated; + template<> struct unrelated<> { + template <class T1, class T2> + auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) // expected-note {{substitution failure}} + -> decltype(t < u) { + return t < u; + } + }; +}; + +void test(int *p) { + using namespace std; + less<>()(p, nullptr); + less<>()(nullptr, p); + less_equal<>()(p, nullptr); + less_equal<>()(nullptr, p); + greater<>()(p, nullptr); + greater<>()(nullptr, p); + greater_equal<>()(p, nullptr); + greater_equal<>()(nullptr, p); + + unrelated<>()(p, nullptr); // expected-error {{no matching function}} +} diff --git a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp index 02431e02e48d..9f9c71a50ce1 100644 --- a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp +++ b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp @@ -8,10 +8,14 @@ // affected are array, pair, priority_queue, stack, and queue. // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DPR28423 // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=pair // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue +// +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__debug +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__profile // MSVC's standard library uses a very similar pattern that relies on delayed // parsing of exception specifications. @@ -21,12 +25,23 @@ #ifdef BE_THE_HEADER #pragma GCC system_header +#ifdef PR28423 +using namespace std; +#endif + namespace std { template<typename T> void swap(T &, T &); template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) { swap(a, b); } +#ifdef NAMESPACE + namespace NAMESPACE { +#define STD_CLASS std::NAMESPACE::CLASS +#else +#define STD_CLASS std::CLASS +#endif + template<typename A, typename B> struct CLASS { #ifdef MSVC void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member))); @@ -42,6 +57,10 @@ namespace std { // void swap(vector &other) noexcept(noexcept(do_swap(member, other.member))); // A member; // }; + +#ifdef NAMESPACE + } +#endif } #else @@ -50,8 +69,8 @@ namespace std { #include __FILE__ struct X {}; -using PX = std::CLASS<X, X>; -using PI = std::CLASS<int, int>; +using PX = STD_CLASS<X, X>; +using PI = STD_CLASS<int, int>; void swap(X &, X &) noexcept; PX px; PI pi; @@ -64,6 +83,7 @@ namespace sad { template<typename A, typename B> struct CLASS { void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}} + // expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}} }; CLASS<int, int> pi; diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 65c8873117ab..105c2e49822f 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s struct Bitfield { - int n : 3 = 7; // expected-error {{bitfield member cannot have an in-class initializer}} + int n : 3 = 7; // expected-error {{bit-field member cannot have an in-class initializer}} }; int a; @@ -13,8 +13,8 @@ public: bool b(); int k; -struct Recurse { - int &n = // expected-error {{cannot use defaulted default constructor of 'Recurse' within the class outside of member functions because 'n' has an initializer}} +struct Recurse { // expected-error {{initializer for 'n' needed}} + int &n = // expected-note {{declared here}} b() ? Recurse().n : // expected-note {{implicit default constructor for 'Recurse' first required here}} k; @@ -87,7 +87,7 @@ namespace PR14838 { struct thing {}; struct another { another() : r(thing()) {} - // expected-error@-1 {{temporary of type 'const PR14838::function' has private destructor}} + // expected-error@-1 {{temporary of type 'PR14838::function' has private destructor}} // expected-warning@-2 {{binding reference member 'r' to a temporary value}} const function &r; // expected-note {{reference member declared here}} } af; @@ -128,8 +128,8 @@ A::A() {} namespace template_default_ctor { struct A { template <typename T> - struct B { - int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'B' within 'A' outside of member functions because 'm1' has an initializer}} + struct B { // expected-error {{initializer for 'm1' needed}} + int m1 = 0; // expected-note {{declared here}} }; // expected-note@+1 {{implicit default constructor for 'template_default_ctor::A::B<int>' first required here}} enum { NOE = noexcept(B<int>()) }; @@ -138,8 +138,8 @@ struct A { namespace default_ctor { struct A { - struct B { - int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'B' within 'A' outside of member functions because 'm1' has an initializer}} + struct B { // expected-error {{initializer for 'm1' needed}} + int m1 = 0; // expected-note {{declared here}} }; // expected-note@+1 {{implicit default constructor for 'default_ctor::A::B' first required here}} enum { NOE = noexcept(B()) }; @@ -150,12 +150,12 @@ namespace member_template { struct A { template <typename T> struct B { - struct C { - int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'C' within 'A' outside of member functions because 'm1' has an initializer}} + struct C { // expected-error {{initializer for 'm1' needed}} + int m1 = 0; // expected-note {{declared here}} }; template <typename U> - struct D { - int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'D' within 'A' outside of member functions because 'm1' has an initializer}} + struct D { // expected-error {{initializer for 'm1' needed}} + int m1 = 0; // expected-note {{declared here}} }; }; enum { diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp index 83aeb019ca81..c8059acd6737 100644 --- a/test/SemaCXX/member-pointer-ms.cpp +++ b/test/SemaCXX/member-pointer-ms.cpp @@ -291,3 +291,11 @@ static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, ""); #pragma pointers_to_members(single) // expected-error{{unexpected 'single'}} #endif + +namespace merging { +struct __single_inheritance S; +struct __single_inheritance S; + +struct __single_inheritance M; // expected-note{{previous inheritance model specified here}} +struct __multiple_inheritance M; // expected-error{{inheritance model does not match previous declaration}} +} diff --git a/test/SemaCXX/microsoft-new-delete.cpp b/test/SemaCXX/microsoft-new-delete.cpp index b929e618a036..beba4d9dd8a4 100644 --- a/test/SemaCXX/microsoft-new-delete.cpp +++ b/test/SemaCXX/microsoft-new-delete.cpp @@ -16,7 +16,7 @@ void *operator new(size_t, const noncopyable&); void *q = new (nc) int[4]; // expected-error {{calling a private constructor}} struct bitfield { int n : 3; } bf; // expected-note {{here}} -void *operator new[](size_t, int &); +void *operator new[](size_t, int &); // expected-note {{passing argument to parameter here}} void *operator new(size_t, const int &); void *r = new (bf.n) int[4]; // expected-error {{non-const reference cannot bind to bit-field}} diff --git a/test/SemaCXX/modules-ts.cppm b/test/SemaCXX/modules-ts.cppm new file mode 100644 index 000000000000..71c09d3bfe6c --- /dev/null +++ b/test/SemaCXX/modules-ts.cppm @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=0 +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DTEST=1 +// RUN: not %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -DTEST=2 2>&1 | FileCheck %s --check-prefix=CHECK-2 +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -Dfoo=bar -DTEST=3 + +#if TEST == 0 +// expected-no-diagnostics +#endif + +module foo; +#if TEST == 1 +// expected-error@-2 {{expected module declaration at start of module interface}} +#elif TEST == 2 +// CHECK-2: error: redefinition of module 'foo' +#endif + +static int m; // ok, internal linkage, so no redefinition error +int n; +#if TEST == 3 +// expected-error@-2 {{redefinition of '}} +// expected-note@-3 {{previous}} +#endif + +#if TEST == 0 +export { + int a; + int b; + constexpr int *p = &n; +} +export int c; + +namespace N { + export void f() {} +} + +export struct T {} t; +#elif TEST == 3 +int use_a = a; // expected-error {{declaration of 'a' must be imported from module 'foo' before it is required}} +// expected-note@-13 {{previous}} + +#undef foo +import foo; + +export {} // expected-error {{export declaration cannot be empty}} +export { ; } +export { static_assert(true); } + +// FIXME: These diagnostics are not very good. +export import foo; // expected-error {{expected unqualified-id}} +export { import foo; } // expected-error {{expected unqualified-id}} + +int use_b = b; +int use_n = n; // FIXME: this should not be visible, because it is not exported + +extern int n; +static_assert(&n == p); // FIXME: these are not the same entity +#endif + + +#if TEST == 1 +struct S { + export int n; // expected-error {{expected member name or ';'}} + export static int n; // expected-error {{expected member name or ';'}} +}; +#endif + +// FIXME: Exports of declarations without external linkage are disallowed. +// Exports of declarations with non-external-linkage types are disallowed. + +// Cannot export within another export. This isn't precisely covered by the +// language rules right now, but (per personal correspondence between zygoloid +// and gdr) is the intent. +#if TEST == 1 +export { + extern "C++" { + namespace NestedExport { + export { // expected-error {{appears within another export}} + int q; + } + } + } +} +#endif diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp new file mode 100644 index 000000000000..461e3c12ff8a --- /dev/null +++ b/test/SemaCXX/ms-uuid.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s + +typedef struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +namespace { +// cl.exe's behavior with merging uuid attributes is a bit erratic: +// * In []-style attributes, a single [] list must not list a duplicate uuid +// (even if it's the same uuid), and only a single declaration of a class +// must have a uuid else the compiler errors out (even if two declarations of +// a class have the same uuid). +// * For __declspec(uuid(...)), it's ok if several declarations of a class have +// an uuid, as long as it's the same uuid each time. If uuids on declarations +// don't match, the compiler errors out. +// * If there are several __declspec(uuid(...))s on one declaration, the +// compiler only warns about this and uses the last uuid. It even warns if +// the uuids are the same. + +// clang-cl implements the following simpler (but largely compatible) behavior +// instead: +// * [] and __declspec uuids have the same behavior. +// * If there are several uuids on a a class (no matter if on the same decl or +// on several decls), it is an error if they don't match. +// * Having several uuids that match is ok. + +// Both cl and clang-cl accept this: +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1; +class __declspec(uuid("000000a0-0000-0000-c000-000000000049")) C1; +class __declspec(uuid("{000000a0-0000-0000-C000-000000000049}")) C1; +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1 {}; + +// Both cl and clang-cl error out on this: +// expected-note@+1 2{{previous uuid specified here}} +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2; +// expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2; +// expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("220000A0-0000-0000-C000-000000000049")) C2 {}; + +// expected-note@+1 {{previous uuid specified here}} +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2_2; +class C2_2; +// expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2; + +// clang-cl accepts this, but cl errors out: +[uuid("000000A0-0000-0000-C000-000000000049")] class C3; +[uuid("000000A0-0000-0000-C000-000000000049")] class C3; +[uuid("000000A0-0000-0000-C000-000000000049")] class C3 {}; + +// Both cl and clang-cl error out on this (but for different reasons): +// expected-note@+1 2{{previous uuid specified here}} +[uuid("000000A0-0000-0000-C000-000000000049")] class C4; +// expected-error@+1 {{uuid does not match previous declaration}} +[uuid("110000A0-0000-0000-C000-000000000049")] class C4; +// expected-error@+1 {{uuid does not match previous declaration}} +[uuid("220000A0-0000-0000-C000-000000000049")] class C4 {}; + +// Both cl and clang-cl error out on this: +// expected-note@+1 {{previous uuid specified here}} +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) +// expected-error@+1 {{uuid does not match previous declaration}} + __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5; + +// expected-note@+1 {{previous uuid specified here}} +[uuid("000000A0-0000-0000-C000-000000000049"), +// expected-error@+1 {{uuid does not match previous declaration}} + uuid("110000A0-0000-0000-C000-000000000049")] class C6; + +// cl doesn't diagnose having one uuid each as []-style attributes and as +// __declspec, even if the uuids differ. clang-cl errors if they differ. +[uuid("000000A0-0000-0000-C000-000000000049")] +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C7; + +// expected-note@+1 {{previous uuid specified here}} +[uuid("000000A0-0000-0000-C000-000000000049")] +// expected-error@+1 {{uuid does not match previous declaration}} +class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C8; + + +// cl warns on this, but clang-cl is fine with it (which is consistent with +// e.g. specifying __multiple_inheritance several times, which cl accepts +// without warning too). +class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) + __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C9; + +// cl errors out on this, but clang-cl is fine with it (to be consistent with +// the previous case). +[uuid("000000A0-0000-0000-C000-000000000049"), + uuid("000000A0-0000-0000-C000-000000000049")] class C10; +} diff --git a/test/SemaCXX/new-delete-cxx0x.cpp b/test/SemaCXX/new-delete-cxx0x.cpp index 899cb4cda87a..c55152510e1b 100644 --- a/test/SemaCXX/new-delete-cxx0x.cpp +++ b/test/SemaCXX/new-delete-cxx0x.cpp @@ -1,13 +1,19 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=i686-pc-linux-gnu void ugly_news(int *ip) { - // These are ill-formed according to one reading of C++98, and at the least - // have undefined behavior. - // FIXME: They're ill-formed in C++11. - (void)new int[-1]; // expected-warning {{array size is negative}} - (void)new int[2000000000]; // expected-warning {{array is too large}} + (void)new int[-1]; // expected-error {{array size is negative}} + (void)new int[2000000000]; // expected-error {{array is too large}} } +void pr22845a() { + constexpr int i = -1; + int *p = new int[i]; // expected-error {{array size is negative}} +} + +void pr22845b() { + constexpr int i = 1; + int *p = new int[i]{1, 2}; // expected-error {{excess elements in array initializer}} +} struct S { S(int); @@ -15,13 +21,14 @@ struct S { ~S(); }; -struct T { // expected-note 2 {{not viable}} - T(int); // expected-note {{not viable}} +struct T { // expected-note 1+{{not viable}} + T(int); // expected-note 1+{{not viable}} }; -void fn() { +void fn(int n) { (void) new int[2] {1, 2}; (void) new S[2] {1, 2}; + (void) new S[3] {1, 2}; // C++11 [expr.new]p19: // If the new-expression creates an object or an array of objects of class // type, access and ambiguity control are done for the allocation function, @@ -29,5 +36,28 @@ void fn() { // // Note that this happens even if the array bound is constant and the // initializer initializes every array element. - (void) new T[2] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 2}} + // + // It's not clear that this is the intended interpretation, however -- we + // obviously don't want to check for a default constructor for 'new S(0)'. + // Instead, we only check for a default constructor in the case of an array + // new with a non-constant bound or insufficient initializers. + (void) new T[2] {1, 2}; // ok + (void) new T[3] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 2}} + (void) new T[n] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of trailing array elements in runtime-sized array new}} +} + +struct U { + T t; // expected-note 3{{in implicit initialization of field 't'}} + S s; +}; +void g(int n) { + // Aggregate initialization, brace-elision, and array new combine to create + // this monstrosity. + (void) new U[2] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 1}} + (void) new U[2] {1, 2, 3}; // ok + (void) new U[2] {1, 2, 3, 4}; // ok + (void) new U[2] {1, 2, 3, 4, 5}; // expected-error {{excess elements in array initializer}} + + (void) new U[n] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of trailing array elements}} + (void) new U[n] {1, 2, 3}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of trailing array elements}} } diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp index 3b42ab44feb9..ee695ff24209 100644 --- a/test/SemaCXX/null_in_arithmetic_ops.cpp +++ b/test/SemaCXX/null_in_arithmetic_ops.cpp @@ -71,8 +71,8 @@ void f() { b = a == NULL || a != NULL; // expected-warning 2{{comparison between NULL and non-pointer ('int' and NULL)}} b = NULL == a || NULL != a; // expected-warning 2{{comparison between NULL and non-pointer (NULL and 'int')}} - b = &a < NULL || NULL < &a || &a > NULL || NULL > &a; - b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a; + b = &a < NULL || NULL < &a || &a > NULL || NULL > &a; // expected-error 4{{ordered comparison between pointer and zero}} + b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a; // expected-error 4{{ordered comparison between pointer and zero}} b = &a == NULL || NULL == &a || &a != NULL || NULL != &a; b = 0 == a; diff --git a/test/SemaCXX/nullability.cpp b/test/SemaCXX/nullability.cpp index c73c01a0a862..160741b1409c 100644 --- a/test/SemaCXX/nullability.cpp +++ b/test/SemaCXX/nullability.cpp @@ -97,3 +97,36 @@ void AssignAndInitNonNullFromFn() { TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} } + +void ConditionalExpr(bool c) { + struct Base {}; + struct Derived : Base {}; + + Base * _Nonnull p; + Base * _Nonnull nonnullB; + Base * _Nullable nullableB; + Derived * _Nonnull nonnullD; + Derived * _Nullable nullableD; + + p = c ? nonnullB : nonnullD; + p = c ? nonnullB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} + p = c ? nullableB : nonnullD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} + p = c ? nullableB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} + p = c ? nonnullD : nonnullB; + p = c ? nonnullD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} + p = c ? nullableD : nonnullB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} + p = c ? nullableD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}} +} + +void arraysInLambdas() { + typedef int INTS[4]; + auto simple = [](int [_Nonnull 2]) {}; + simple(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} + auto nested = [](void *_Nullable [_Nonnull 2]) {}; + nested(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} + auto nestedBad = [](int [2][_Nonnull 2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}} + + auto withTypedef = [](INTS _Nonnull) {}; + withTypedef(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}} + auto withTypedefBad = [](INTS _Nonnull[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}} +} diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index 7d765b482c73..9a092910b6f9 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion -Wno-tautological-compare %s #include <stdint.h> typedef decltype(nullptr) nullptr_t; @@ -32,17 +32,17 @@ nullptr_t f(nullptr_t null) // Operators (void)(null == nullptr); - (void)(null <= nullptr); + (void)(null <= nullptr); // expected-error {{invalid operands to binary expression}} (void)(null == 0); (void)(null == (void*)0); (void)((void*)0 == nullptr); - (void)(null <= 0); - (void)(null <= (void*)0); - (void)((void*)0 <= nullptr); + (void)(null <= 0); // expected-error {{invalid operands to binary expression}} + (void)(null <= (void*)0); // expected-error {{invalid operands to binary expression}} + (void)((void*)0 <= nullptr); // expected-error {{invalid operands to binary expression}} (void)(0 == nullptr); (void)(nullptr == 0); - (void)(nullptr <= 0); - (void)(0 <= nullptr); + (void)(nullptr <= 0); // expected-error {{invalid operands to binary expression}} + (void)(0 <= nullptr); // expected-error {{invalid operands to binary expression}} (void)(1 > nullptr); // expected-error {{invalid operands to binary expression}} (void)(1 != nullptr); // expected-error {{invalid operands to binary expression}} (void)(1 + nullptr); // expected-error {{invalid operands to binary expression}} @@ -118,24 +118,24 @@ static_assert(__is_scalar(nullptr_t), ""); static_assert(__is_pod(nullptr_t), ""); static_assert(sizeof(nullptr_t) == sizeof(void*), ""); -static_assert(!(nullptr < nullptr), ""); -static_assert(!(nullptr > nullptr), ""); -static_assert( nullptr <= nullptr, ""); -static_assert( nullptr >= nullptr, ""); +static_assert(!(nullptr < nullptr), ""); // expected-error {{invalid operands to binary expression}} +static_assert(!(nullptr > nullptr), ""); // expected-error {{invalid operands to binary expression}} +static_assert( nullptr <= nullptr, ""); // expected-error {{invalid operands to binary expression}} +static_assert( nullptr >= nullptr, ""); // expected-error {{invalid operands to binary expression}} static_assert( nullptr == nullptr, ""); static_assert(!(nullptr != nullptr), ""); -static_assert(!(0 < nullptr), ""); -static_assert(!(0 > nullptr), ""); -static_assert( 0 <= nullptr, ""); -static_assert( 0 >= nullptr, ""); +static_assert(!(0 < nullptr), ""); // expected-error {{invalid operands to binary expression}} +static_assert(!(0 > nullptr), ""); // expected-error {{invalid operands to binary expression}} +static_assert( 0 <= nullptr, ""); // expected-error {{invalid operands to binary expression}} +static_assert( 0 >= nullptr, ""); // expected-error {{invalid operands to binary expression}} static_assert( 0 == nullptr, ""); static_assert(!(0 != nullptr), ""); -static_assert(!(nullptr < 0), ""); -static_assert(!(nullptr > 0), ""); -static_assert( nullptr <= 0, ""); -static_assert( nullptr >= 0, ""); +static_assert(!(nullptr < 0), ""); // expected-error {{invalid operands to binary expression}} +static_assert(!(nullptr > 0), ""); // expected-error {{invalid operands to binary expression}} +static_assert( nullptr <= 0, ""); // expected-error {{invalid operands to binary expression}} +static_assert( nullptr >= 0, ""); // expected-error {{invalid operands to binary expression}} static_assert( nullptr == 0, ""); static_assert(!(nullptr != 0), ""); @@ -154,10 +154,10 @@ namespace overloading { void test_conversion(ConvertsToNullPtr ctn) { (void)(ctn == ctn); (void)(ctn != ctn); - (void)(ctn <= ctn); - (void)(ctn >= ctn); - (void)(ctn < ctn); - (void)(ctn > ctn); + (void)(ctn <= ctn); // expected-error {{invalid operands to binary expression}} + (void)(ctn >= ctn); // expected-error {{invalid operands to binary expression}} + (void)(ctn < ctn); // expected-error {{invalid operands to binary expression}} + (void)(ctn > ctn); // expected-error {{invalid operands to binary expression}} } } diff --git a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp index 60b4670b3a5e..6273d9c42e0b 100644 --- a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp +++ b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp @@ -45,12 +45,12 @@ void foo() { b = a == nullptr || nullptr == a; // expected-error 2{{invalid operands to binary expression}} b = a != nullptr || nullptr != a; // expected-error 2{{invalid operands to binary expression}} - b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a; - b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a; + b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a; // expected-error 4{{invalid operands}} + b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a; // expected-error 4{{invalid operands}} b = &a == nullptr || nullptr == &a || &a != nullptr || nullptr != &a; - b = nullptr < nullptr || nullptr > nullptr; - b = nullptr <= nullptr || nullptr >= nullptr; + b = nullptr < nullptr || nullptr > nullptr; // expected-error 2{{invalid operands to binary expression}} + b = nullptr <= nullptr || nullptr >= nullptr; // expected-error 2{{invalid operands to binary expression}} b = nullptr == nullptr || nullptr != nullptr; b = ((nullptr)) != a; // expected-error{{invalid operands to binary expression}} diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 7eaf98b601c1..3a01bf24b31a 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -647,3 +647,14 @@ namespace PR20218 { g(y); // expected-error {{ambiguous}} } } + +namespace StringLiteralToCharAmbiguity { + void f(char *, int); + void f(const char *, unsigned); + void g() { f("foo", 0); } +#if __cplusplus <= 199711L + // expected-error@-2 {{call to 'f' is ambiguous}} + // expected-note@-5 {{candidate function}} + // expected-note@-5 {{candidate function}} +#endif +} diff --git a/test/SemaCXX/pr28050.cpp b/test/SemaCXX/pr28050.cpp new file mode 100644 index 000000000000..57e90eb75169 --- /dev/null +++ b/test/SemaCXX/pr28050.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++11 %s -fsyntax-only +// +// expected-no-diagnostics + +class A { +public: + A(char *s) {} + A(A &&) = delete; +}; + +int main() { A a("OK"); } diff --git a/test/SemaCXX/predefined-expr.cpp b/test/SemaCXX/predefined-expr.cpp index f4a155da6678..8cba0d41a299 100644 --- a/test/SemaCXX/predefined-expr.cpp +++ b/test/SemaCXX/predefined-expr.cpp @@ -33,11 +33,10 @@ int baz() { (); ^{ - static_assert(sizeof(__func__) == 27, "___Z3bazIiEiv_block_invoke"); - static_assert(sizeof(__FUNCTION__) == 27, "___Z3bazIiEiv_block_invoke"); - static_assert(sizeof(__PRETTY_FUNCTION__) == 27, "___Z3bazIiEiv_block_invoke"); - } - (); + static_assert(sizeof(__func__) == 17, "baz_block_invoke"); + static_assert(sizeof(__FUNCTION__) == 17, "baz_block_invoke"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 33, "int baz() [T = int]_block_invoke"); + }(); #pragma clang __debug captured { @@ -64,11 +63,10 @@ int main() { (); ^{ - static_assert(sizeof(__func__) == 20, "__main_block_invoke"); - static_assert(sizeof(__FUNCTION__) == 20, "__main_block_invoke"); - static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "__main_block_invoke"); - } - (); + static_assert(sizeof(__func__) == 18, "main_block_invoke"); + static_assert(sizeof(__FUNCTION__) == 18, "main_block_invoke"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 24, "int main()_block_invoke"); + }(); #pragma clang __debug captured { diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index 7c88dc0302ad..6cc46d8b0d9f 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -125,7 +125,7 @@ void const_arrays() { namespace PR9564 { struct a { int a : 10; }; a x; - int *y = &reinterpret_cast<int&>(x.a); // expected-error {{not allowed}} + int *y = &reinterpret_cast<int&>(x.a); // expected-error {{reinterpret_cast from bit-field lvalue to reference type 'int &'}} __attribute((ext_vector_type(4))) typedef float v4; float& w(v4 &a) { return reinterpret_cast<float&>(a[1]); } // expected-error {{not allowed}} diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp index 4c2050494b69..94b09ce2cb2a 100644 --- a/test/SemaCXX/rval-references.cpp +++ b/test/SemaCXX/rval-references.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s typedef int&& irr; typedef irr& ilr_c1; // Collapses to int& @@ -30,11 +30,15 @@ void f() { int &&virr2 = 0; int &&virr3 = virr2; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}} int i1 = 0; + const double d1 = 0; + const int ci1 = 1; int &&virr4 = i1; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}} int &&virr5 = ret_irr(); int &&virr6 = static_cast<int&&>(i1); - (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}} - + (void)static_cast<not_int &&>(i1); // expected-error {{reference to type 'not_int' could not bind to an lvalue of type 'int'}} + (void)static_cast<int &&>(static_cast<int const&&>(i1)); // expected-error {{cannot cast from rvalue of type 'const int' to rvalue reference type 'int &&'}} + (void)static_cast<int &&>(ci1); // expected-error {{types are not compatible}} + (void)static_cast<int &&>(d1); int i2 = over(i1); not_int ni1 = over(0); int i3 = over(virr2); diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp index 392dcd869802..0c60ce02097b 100644 --- a/test/SemaCXX/switch.cpp +++ b/test/SemaCXX/switch.cpp @@ -100,3 +100,33 @@ namespace Conversion { } template void f(S); // expected-note {{instantiation of}} } + +// rdar://29230764 +namespace OpaqueEnumWarnings { + +enum Opaque : int; +enum class OpaqueClass : int; + +enum class Defined : int; +enum class Defined : int { a }; + +void test(Opaque o, OpaqueClass oc, Defined d) { + // Don't warn that case value is not present in opaque enums. + switch (o) { + case (Opaque)1: + break; + } + switch (oc) { + case (OpaqueClass)1: + break; + } + + switch (d) { + case Defined::a: + break; + case (Defined)2: // expected-warning {{case value not in enumerated type 'OpaqueEnumWarnings::Defined'}} + break; + } +} + +} diff --git a/test/SemaCXX/template-ambiguous-overload.cpp b/test/SemaCXX/template-ambiguous-overload.cpp new file mode 100644 index 000000000000..bbb7e397b844 --- /dev/null +++ b/test/SemaCXX/template-ambiguous-overload.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace n { +template <int> +void f(); // expected-note{{explicit instantiation candidate function 'n::f<0>' template here [with $0 = 0]}} + +extern template void f<0>(); +} + +using namespace n; + +template <int> +void f() {} // expected-note{{explicit instantiation candidate function 'f<0>' template here [with $0 = 0]}} + +template void f<0>(); // expected-error{{partial ordering for explicit instantiation of 'f' is ambiguous}} + diff --git a/test/SemaCXX/type-definition-in-specifier.cpp b/test/SemaCXX/type-definition-in-specifier.cpp index 43443a00e44b..74ba058b4f12 100644 --- a/test/SemaCXX/type-definition-in-specifier.cpp +++ b/test/SemaCXX/type-definition-in-specifier.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -verify %s struct S0; struct S1; @@ -30,7 +30,7 @@ struct pr19018 { void pr19018_1 (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}} void pr19018_1a (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}} -e19018_1 x2; // expected-error{{unknown type name 'e19018_1'}} +e19018_1 x2; void pr19018_2 (enum {qq} x); // expected-error{{cannot be defined in a parameter type}} void pr19018_3 (struct s19018_2 {int qq;} x); // expected-error{{cannot be defined in a parameter type}} @@ -53,14 +53,19 @@ struct pr19018a { struct s19018b { void func1 (enum en_2 {qq} x); // expected-error{{cannot be defined in a parameter type}} - en_2 x1; // expected-error{{unknown type name 'en_2'}} + en_2 x1; void func2 (enum en_3 {qq} x); // expected-error{{cannot be defined in a parameter type}} - enum en_3 x2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} \ - // expected-error{{field has incomplete type 'enum en_3'}} \ - // expected-note{{forward declaration of 'en_3'}} + enum en_3 x2; }; struct pr18963 { - short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}} - long foo5 (float foo6 = foo4); // expected-error{{use of undeclared identifier 'foo4'}} + short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}} \ + // expected-note{{declared here}} + + long foo5 (float foo6 = foo4); // expected-error{{'foo4' does not refer to a value}} }; + +// expected-error@+2 {{cannot be defined in a parameter type}} +// expected-note@+1 {{previous definition is here}} +void func_with_eh_and_type(struct type_in_eh {} o) throw(int) {} +struct type_in_eh {}; // expected-error {{redefinition of 'type_in_eh'}} diff --git a/test/SemaCXX/unknown-anytype.cpp b/test/SemaCXX/unknown-anytype.cpp index 95ad04093405..78a01ba2d358 100644 --- a/test/SemaCXX/unknown-anytype.cpp +++ b/test/SemaCXX/unknown-anytype.cpp @@ -56,3 +56,15 @@ namespace test5 { (X<int>)test0(); // expected-error{{implicit instantiation of undefined template 'test5::X<int>'}} } } + +namespace test6 { + extern __unknown_anytype func(); + extern __unknown_anytype var; + double *d; + + void test() { + d = (double*)&func(); // expected-error{{address-of operator cannot be applied to a call to a function with unknown return type}} + d = (double*)&var; + } + +} diff --git a/test/SemaCXX/using-decl-templates.cpp b/test/SemaCXX/using-decl-templates.cpp index d766bb3ac6bf..d5cc3a08eb75 100644 --- a/test/SemaCXX/using-decl-templates.cpp +++ b/test/SemaCXX/using-decl-templates.cpp @@ -90,5 +90,14 @@ namespace aliastemplateinst { template<typename T> struct A { }; template<typename T> using APtr = A<T*>; // expected-note{{previous use is here}} - template struct APtr<int>; // expected-error{{elaborated type refers to a type alias template}} + template struct APtr<int>; // expected-error{{type alias template 'APtr' cannot be referenced with a struct specifier}} } + +namespace DontDiagnoseInvalidTest { +template <bool Value> struct Base { + static_assert(Value, ""); // expected-error {{static_assert failed}} +}; +struct Derived : Base<false> { // expected-note {{requested here}} + using Base<false>::Base; // OK. Don't diagnose that 'Base' isn't a base class of Derived. +}; +} // namespace DontDiagnoseInvalidTest diff --git a/test/SemaCXX/vartemplate-lambda.cpp b/test/SemaCXX/vartemplate-lambda.cpp index 9dab6da3d1e3..5b91e232e3a6 100644 --- a/test/SemaCXX/vartemplate-lambda.cpp +++ b/test/SemaCXX/vartemplate-lambda.cpp @@ -1,18 +1,36 @@ // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s -// expected-no-diagnostics template <class> auto fn0 = [] {}; template <typename> void foo0() { fn0<char>(); } template<typename T> auto fn1 = [](auto a) { return a + T(1); }; +template<typename T> auto v1 = [](int a = T(1)) { return a; }(); + +struct S { + template<class T> + static constexpr T t = [](int f = T(7)){return f;}(); // expected-error{{constexpr variable 't<int>' must be initialized by a constant expression}} expected-error{{a lambda expression may not appear inside of a constant expression}} expected-note{{cannot be used in a constant expression}} +}; template <typename X> int foo2() { X a = 0x61; fn1<char>(a); + (void)v1<int>; + (void)S::t<int>; // expected-note{{in instantiation of static data member 'S::t<int>' requested here}} return 0; } +template<class C> +int foo3() { + C::m1(); // expected-error{{type 'long long' cannot be used prior to '::' because it has no members}} + return 1; +} + +template<class C> +auto v2 = [](int a = foo3<C>()){}; // expected-note{{in instantiation of function template specialization 'foo3<long long>' requested here}} + int main() { + v2<long long>(); // This line causes foo3<long long> to be instantiated. + v2<long long>(2); // This line does not. foo2<int>(); } diff --git a/test/SemaCXX/warn-c++1z-extensions.cpp b/test/SemaCXX/warn-c++1z-extensions.cpp new file mode 100644 index 000000000000..9b5e1c205cf3 --- /dev/null +++ b/test/SemaCXX/warn-c++1z-extensions.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s + +void f() { + if (bool b = true; b) {} // expected-warning {{'if' initialization statements are a C++1z extension}} + switch (int n = 5; n) { // expected-warning {{'switch' initialization statements are a C++1z extension}} + case 5: break; + } +} diff --git a/test/SemaCXX/warn-everthing.cpp b/test/SemaCXX/warn-everthing.cpp index ad3dd8a24d88..ff66c78cdf97 100644 --- a/test/SemaCXX/warn-everthing.cpp +++ b/test/SemaCXX/warn-everthing.cpp @@ -9,5 +9,5 @@ public: }; void testPR12271() { // expected-warning {{no previous prototype for function 'testPR12271'}} - PR12271 a[1][1]; // expected-warning {{unused variable 'a'}} + PR12271 a[1][1]; } diff --git a/test/SemaCXX/warn-logical-not-compare.cpp b/test/SemaCXX/warn-logical-not-compare.cpp index 280ab22d7235..8b332c3c0e8a 100644 --- a/test/SemaCXX/warn-logical-not-compare.cpp +++ b/test/SemaCXX/warn-logical-not-compare.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s bool getBool(); int getInt(); @@ -189,6 +189,45 @@ bool test2 (E e) { return ret; } +bool test_bitwise_op(int x) { + bool ret; + + ret = !x & 1; + // expected-warning@-1 {{logical not is only applied to the left hand side of this bitwise operator}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the bitwise operator first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: warn-logical-not-compare.cpp:[[line:[0-9]*]]:9: warning + // CHECK: to evaluate the bitwise operator first + // CHECK: fix-it:"{{.*}}":{[[line]]:10-[[line]]:10}:"(" + // CHECK: fix-it:"{{.*}}":{[[line]]:15-[[line]]:15}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{[[line]]:9-[[line]]:9}:"(" + // CHECK: fix-it:"{{.*}}":{[[line]]:11-[[line]]:11}:")" + ret = !(x & 1); + ret = (!x) & 1; + + // This warning is really about !x & FOO since that's a common misspelling + // of the negated bit test !(x & FOO). Don't warn for | and ^, since + // it's at least conceivable that the user wants to use | as an + // alternative to || that evaluates both branches. (The warning above is + // only emitted if the operand to ! is not a bool, but in C that's common.) + // And there's no logical ^. + ret = !x | 1; + ret = !(x | 1); + ret = (!x) | 1; + + ret = !x ^ 1; + ret = !(x ^ 1); + ret = (!x) ^ 1; + + // These already err, don't also warn. + !x &= 1; // expected-error{{expression is not assignable}} + !x |= 1; // expected-error{{expression is not assignable}} + !x ^= 1; // expected-error{{expression is not assignable}} + + return ret; +} + bool PR16673(int x) { bool ret; // Make sure we don't emit a fixit for the left paren, but not the right paren. diff --git a/test/SemaCXX/warn-max-unsigned-zero.cpp b/test/SemaCXX/warn-max-unsigned-zero.cpp new file mode 100644 index 000000000000..5564b101d8ec --- /dev/null +++ b/test/SemaCXX/warn-max-unsigned-zero.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fsyntax-only -Wmax-unsigned-zero -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -Wmax-unsigned-zero %s -std=c++11 -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s + +namespace std { +template <typename T> +T max(const T &, const T &); +} + +void test(unsigned u) { + auto a = std::max(55u, 0u); + // expected-warning@-1{{taking the max of a value and unsigned zero is always equal to the other value}} + // expected-note@-2{{remove call to max function and unsigned zero argument}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:28}:"" + auto b = std::max(u, 0u); + // expected-warning@-1{{taking the max of a value and unsigned zero is always equal to the other value}} + // expected-note@-2{{remove call to max function and unsigned zero argument}} + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{13:12-13:20}:"" + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{13:22-13:26}:"" + auto c = std::max(0u, 55u); + // expected-warning@-1{{taking the max of unsigned zero and a value is always equal to the other value}} + // expected-note@-2{{remove call to max function and unsigned zero argument}} + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{16:12-16:20}:"" + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{16:21-16:24}:"" + auto d = std::max(0u, u); + // expected-warning@-1{{taking the max of unsigned zero and a value is always equal to the other value}} + // expected-note@-2{{remove call to max function and unsigned zero argument}} + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{19:12-19:20}:"" + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{19:21-19:24}:"" +} + +void negative_test(signed s) { + auto a = std::max(0, s); + auto b = std::max(s, 0); + auto c = std::max(22, 0); + auto d = std::max(0, 22); +} + +template <unsigned x> +unsigned template_test() { + return std::max(x, 0u); + // expected-warning@-1{{taking the max of a value and unsigned zero is always equal to the other value}} + // expected-note@-2{{remove call to max function and unsigned zero argument}} + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{33:10-33:18}:"" + // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{33:20-33:24}:"" +} + +int a = template_test<0>() + template_test<1>() + template_test<2>(); + +#define comp(x,y) std::max(x, y) + +int b = comp(0, 1); +int c = comp(0u, 1u); +int d = comp(2u, 0u); + diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp index cca15fc8ef3c..0a78caa924ea 100644 --- a/test/SemaCXX/warn-memset-bad-sizeof.cpp +++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wno-sizeof-array-argument %s // +extern "C" void *bzero(void *, unsigned); 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); @@ -47,6 +48,19 @@ void f(Mat m, const Foo& const_foo, char *buffer) { memset(heap_buffer, 0, sizeof(heap_buffer)); // \ // expected-warning {{'memset' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}} + bzero(&s, sizeof(&s)); // \ + // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} + bzero(ps, sizeof(ps)); // \ + // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} + bzero(ps2, sizeof(ps2)); // \ + // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'PS' (aka 'S *')}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} + bzero(ps2, sizeof(typeof(ps2))); // \ + // expected-warning {{argument to 'sizeof' in 'bzero' call is the same pointer type}} + bzero(ps2, sizeof(PS)); // \ + // expected-warning {{argument to 'sizeof' in 'bzero' call is the same pointer type}} + bzero(heap_buffer, sizeof(heap_buffer)); // \ + // expected-warning {{'bzero' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}} + memcpy(&s, 0, sizeof(&s)); // \ // expected-warning {{'memcpy' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} memcpy(0, &s, sizeof(&s)); // \ @@ -73,6 +87,21 @@ void f(Mat m, const Foo& const_foo, char *buffer) { memset(arr, 0, sizeof(arr)); memset(parr, 0, sizeof(parr)); + bzero((void*)&s, sizeof(&s)); + bzero(&s, sizeof(s)); + bzero(&s, sizeof(S)); + bzero(&s, sizeof(const S)); + bzero(&s, sizeof(volatile S)); + bzero(&s, sizeof(volatile const S)); + bzero(&foo, sizeof(CFoo)); + bzero(&foo, sizeof(VFoo)); + bzero(&foo, sizeof(CVFoo)); + bzero(ps, sizeof(*ps)); + bzero(ps2, sizeof(*ps2)); + bzero(ps2, sizeof(typeof(*ps2))); + bzero(arr, sizeof(arr)); + bzero(parr, sizeof(parr)); + memcpy(&foo, &const_foo, sizeof(Foo)); memcpy((void*)&s, 0, sizeof(&s)); memcpy(0, (void*)&s, sizeof(&s)); @@ -96,12 +125,17 @@ void f(Mat m, const Foo& const_foo, char *buffer) { int iarr[14]; memset(&iarr[0], 0, sizeof iarr); memset(iarr, 0, sizeof iarr); + bzero(&iarr[0], sizeof iarr); + bzero(iarr, sizeof iarr); int* iparr[14]; memset(&iparr[0], 0, sizeof iparr); memset(iparr, 0, sizeof iparr); + bzero(&iparr[0], sizeof iparr); + bzero(iparr, sizeof iparr); memset(m, 0, sizeof(Mat)); + bzero(m, sizeof(Mat)); // Copy to raw buffer shouldn't warn either memcpy(&foo, &arr, sizeof(Foo)); @@ -114,12 +148,21 @@ void f(Mat m, const Foo& const_foo, char *buffer) { for (;;) {} &s; }), 0, sizeof(s)); + + bzero(({ + if (0) {} + while (0) {} + for (;;) {} + &s; + }), sizeof(s)); } namespace ns { void memset(void* s, char c, int n); +void bzero(void* s, int n); void f(int* i) { memset(i, 0, sizeof(i)); + bzero(i, sizeof(i)); } } diff --git a/test/SemaCXX/warn-memsize-comparison.cpp b/test/SemaCXX/warn-memsize-comparison.cpp index 54c410e3dc0b..b5c7a9d6969c 100644 --- a/test/SemaCXX/warn-memsize-comparison.cpp +++ b/test/SemaCXX/warn-memsize-comparison.cpp @@ -5,7 +5,7 @@ typedef __SIZE_TYPE__ size_t; extern "C" void *memset(void *, int, size_t); extern "C" void *memmove(void *s1, const void *s2, size_t n); extern "C" void *memcpy(void *s1, const void *s2, size_t n); -extern "C" void *memcmp(void *s1, const void *s2, size_t n); +extern "C" int memcmp(void *s1, const void *s2, size_t n); extern "C" int strncmp(const char *s1, const char *s2, size_t n); extern "C" int strncasecmp(const char *s1, const char *s2, size_t n); extern "C" char *strncpy(char *dst, const char *src, size_t n); @@ -28,11 +28,12 @@ void f() { expected-note {{explicitly cast the argument}} if (memmove(b1, b2, sizeof(b1)) == 0) {} + // FIXME: This fixit is bogus. if (memcpy(b1, b2, sizeof(b1) < 0)) {} // \ expected-warning{{size argument in 'memcpy' call is a comparison}} \ expected-note {{did you mean to compare}} \ expected-note {{explicitly cast the argument}} - if (memcpy(b1, b2, sizeof(b1)) < 0) {} + if (memcpy(b1, b2, sizeof(b1)) < 0) {} // expected-error {{ordered comparison between pointer and zero}} if (memcmp(b1, b2, sizeof(b1) <= 0)) {} // \ expected-warning{{size argument in 'memcmp' call is a comparison}} \ @@ -58,11 +59,12 @@ void f() { expected-note {{explicitly cast the argument}} if (strncpy(b1, b2, sizeof(b1)) == 0 || true) {} + // FIXME: This fixit is bogus. if (strncat(b1, b2, sizeof(b1) - 1 >= 0 && true)) {} // \ expected-warning{{size argument in 'strncat' call is a comparison}} \ expected-note {{did you mean to compare}} \ expected-note {{explicitly cast the argument}} - if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {} + if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {} // expected-error {{ordered comparison between pointer and zero}} if (strndup(b1, sizeof(b1) != 0)) {} // \ expected-warning{{size argument in 'strndup' call is a comparison}} \ diff --git a/test/SemaCXX/warn-missing-variable-declarations.cpp b/test/SemaCXX/warn-missing-variable-declarations.cpp index ad23e0429bbd..5b882845f3c6 100644 --- a/test/SemaCXX/warn-missing-variable-declarations.cpp +++ b/test/SemaCXX/warn-missing-variable-declarations.cpp @@ -47,3 +47,8 @@ class C { static int x = 0; // no-warn } }; + +// There is also no need to use static in anonymous namespaces. +namespace { + int vgood4; +} diff --git a/test/SemaCXX/warn-msvc-enum-bitfield.cpp b/test/SemaCXX/warn-msvc-enum-bitfield.cpp new file mode 100644 index 000000000000..99e1669018ab --- /dev/null +++ b/test/SemaCXX/warn-msvc-enum-bitfield.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -Wsigned-enum-bitfield -verify %s --std=c++11 + +// Enums used in bitfields with no explicitly specified underlying type. +void test0() { + enum E { E1, E2 }; + enum F { F1, F2 }; + struct { E e1 : 1; E e2; F f1 : 1; F f2; } s; + + s.e1 = E1; // expected-warning {{enums in the Microsoft ABI are signed integers by default; consider giving the enum E an unsigned underlying type to make this code portable}} + s.f1 = F1; // expected-warning {{enums in the Microsoft ABI are signed integers by default; consider giving the enum F an unsigned underlying type to make this code portable}} + + s.e2 = E2; + s.f2 = F2; +} + +// Enums used in bitfields with an explicit signed underlying type. +void test1() { + enum E : signed { E1, E2 }; + enum F : long { F1, F2 }; + struct { E e1 : 1; E e2; F f1 : 1; F f2; } s; + + s.e1 = E1; + s.f1 = F1; + + s.e2 = E2; + s.f2 = F2; +} + +// Enums used in bitfields with an explicitly unsigned underlying type. +void test3() { + enum E : unsigned { E1, E2 }; + enum F : unsigned long { F1, F2 }; + struct { E e1 : 1; E e2; F f1 : 1; F f2; } s; + + s.e1 = E1; + s.f1 = F1; + + s.e2 = E2; + s.f2 = F2; +} diff --git a/test/SemaCXX/warn-range-loop-analysis.cpp b/test/SemaCXX/warn-range-loop-analysis.cpp index 91756b970e97..98c4a18776a1 100644 --- a/test/SemaCXX/warn-range-loop-analysis.cpp +++ b/test/SemaCXX/warn-range-loop-analysis.cpp @@ -29,7 +29,7 @@ struct Bar { // test1-6 are set in pairs, the odd numbers are the non-reference returning // versions of the even numbers. // test7-9 use an array instead of a range object -// tests use all four versions of the loop varaible, const &T, const T, T&, and +// tests use all four versions of the loop variable, const &T, const T, T&, and // T. Versions producing errors and are commented out. // // Conversion chart: diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp new file mode 100644 index 000000000000..575664482dbe --- /dev/null +++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s +// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s +// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s + +void foo(int param) { // expected-note 1+ {{previous declaration is here}} + int var = 0; // expected-note 1+ {{previous declaration is here}} + + // Avoid warnings for variables that aren't implicitly captured. + { +#ifdef AVOID + auto f1 = [=] { int var = 1; }; // no warning + auto f2 = [&] { int var = 2; }; // no warning + auto f3 = [=] (int param) { ; }; // no warning + auto f4 = [&] (int param) { ; }; // no warning +#else + auto f1 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f2 = [&] { int var = 2; }; // expected-warning {{declaration shadows a local variable}} + auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} +#endif + } + + // Warn for variables that are implicitly captured. + { + auto f1 = [=] () { + { + int var = 1; // expected-warning {{declaration shadows a local variable}} + } + int x = var; // expected-note {{variable 'var' is captured here}} + }; + auto f2 = [&] +#ifdef AVOID + (int param) { +#else + (int param) { // expected-warning {{declaration shadows a local variable}} +#endif + int x = var; // expected-note {{variable 'var' is captured here}} + int var = param; // expected-warning {{declaration shadows a local variable}} + }; + } + + // Warn for variables that are explicitly captured when a lambda has a default + // capture specifier. + { + auto f1 = [=, &var] () { // expected-note {{variable 'var' is captured here}} + int x = param; // expected-note {{variable 'param' is captured here}} + int var = 0; // expected-warning {{declaration shadows a local variable}} + int param = 0; // expected-warning {{declaration shadows a local variable}} + }; + } + + // Warn normally inside of lambdas. + auto l1 = [] { // expected-note {{previous declaration is here}} + int x = 1; // expected-note {{previous declaration is here}} + { int x = 2; } // expected-warning {{declaration shadows a local variable}} + }; + auto l2 = [] (int x) { // expected-note {{previous declaration is here}} + { int x = 1; } // expected-warning {{declaration shadows a local variable}} + }; + + // Avoid warnings for variables that aren't explicitly captured. + { +#ifdef AVOID + auto f1 = [] { int var = 1; }; // no warning + auto f2 = [] (int param) { ; }; // no warning + auto f3 = [param] () { int var = 1; }; // no warning + auto f4 = [var] (int param) { ; }; // no warning +#else + auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} +#endif + }; + + // Warn for variables that are explicitly captured. + { + auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}} + int var = 1; // expected-warning {{declaration shadows a local variable}} + }; + auto f2 = [param] // expected-note {{variable 'param' is explicitly captured here}} + (int param) { ; }; // expected-warning {{declaration shadows a local variable}} + } + + // Warn for variables defined in the capture list. + auto l3 = [z = var] { // expected-note {{previous declaration is here}} +#ifdef AVOID + int var = 1; // no warning +#else + int var = 1; // expected-warning {{declaration shadows a local variable}} +#endif + { int z = 1; } // expected-warning {{declaration shadows a local variable}} + }; +#ifdef AVOID + auto l4 = [var = param] (int param) { ; }; // no warning +#else + auto l4 = [var = param] (int param) { ; }; // expected-warning {{declaration shadows a local variable}} +#endif + + // Make sure that inner lambdas work as well. + auto l5 = [var, l1] { // expected-note {{variable 'l1' is explicitly captured here}} + auto l1 = [] { // expected-warning {{declaration shadows a local variable}} +#ifdef AVOID + int var = 1; // no warning +#else + int var = 1; // expected-warning {{declaration shadows a local variable}} +#endif + }; +#ifdef AVOID + auto f1 = [] { int var = 1; }; // no warning + auto f2 = [=] { int var = 1; }; // no warning +#else + auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f2 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}} +#endif + auto f3 = [var] // expected-note {{variable 'var' is explicitly captured here}} + { int var = 1; }; // expected-warning {{declaration shadows a local variable}} + auto f4 = [&] { + int x = var; // expected-note {{variable 'var' is captured here}} + int var = 2; // expected-warning {{declaration shadows a local variable}} + }; + }; + auto l6 = [&] { + auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}} + int param = 0; // expected-warning {{declaration shadows a local variable}} + }; + }; + + // Generic lambda arguments should work. +#ifdef AVOID + auto g1 = [](auto param) { ; }; // no warning + auto g2 = [=](auto param) { ; }; // no warning +#else + auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}} + auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}} +#endif + auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}} + (auto param) { ; }; // expected-warning {{declaration shadows a local variable}} +} diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 8dcbe7271d69..d7be785b35a6 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -150,3 +150,47 @@ namespace ctor_with_cleanups { } #include "Inputs/warn-unused-variables.h" + +namespace arrayRecords { + +class NonTriviallyDestructible { +public: + ~NonTriviallyDestructible() {} +}; + +struct Foo { + int x; + Foo(int x) : x(x) {} +}; + +struct Elidable { + Elidable(); +}; + +void foo(int size) { + Elidable elidable; // no warning + Elidable elidableArray[2]; // no warning + Elidable elidableDynArray[size]; // no warning + Elidable elidableNestedArray[1][2][3]; // no warning + + NonTriviallyDestructible scalar; // no warning + NonTriviallyDestructible array[2]; // no warning + NonTriviallyDestructible nestedArray[2][2]; // no warning + + Foo fooScalar = 1; // expected-warning {{unused variable 'fooScalar'}} + Foo fooArray[] = {1,2}; // expected-warning {{unused variable 'fooArray'}} + Foo fooNested[2][2] = { {1,2}, {3,4} }; // expected-warning {{unused variable 'fooNested'}} +} + +template<int N> +void bar() { + NonTriviallyDestructible scaler; // no warning + NonTriviallyDestructible array[N]; // no warning +} + +void test() { + foo(10); + bar<2>(); +} + +} diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp index d30665387153..e678f9e461ef 100644 --- a/test/SemaCXX/warn-weak-vtables.cpp +++ b/test/SemaCXX/warn-weak-vtables.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -triple %itanium_abi_triple -Wweak-vtables -Wweak-template-vtables -// RUN: %clang_cc1 %s -fsyntax-only -triple %ms_abi_triple -Werror -Wno-weak-vtables -Wno-weak-template-vtables +// +// Check that this warning is disabled on MS ABI targets which don't have key +// functions. +// RUN: %clang_cc1 %s -fsyntax-only -triple %ms_abi_triple -Werror -Wweak-vtables -Wweak-template-vtables struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} virtual void f() { } |