diff options
Diffstat (limited to 'test/SemaCXX')
40 files changed, 1893 insertions, 54 deletions
diff --git a/test/SemaCXX/Inputs/warn-unused-variables.h b/test/SemaCXX/Inputs/warn-unused-variables.h new file mode 100644 index 0000000..5fac459 --- /dev/null +++ b/test/SemaCXX/Inputs/warn-unused-variables.h @@ -0,0 +1,11 @@ +// Verify that we don't warn about variables of internal-linkage type in +// headers, as the use may be in another TU. +namespace PR15558 { +namespace { +class A {}; +} + +class B { + static A a; +}; +} diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 449e24b..ab3ff69 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -208,3 +208,128 @@ void ::f(); // expected-warning{{extra qualification on member 'f'}} class C { C::C(); // expected-warning{{extra qualification on member 'C'}} }; + +struct StructWithProperty { + __declspec(property(get=GetV)) int V1; + __declspec(property(put=SetV)) int V2; + __declspec(property(get=GetV, put=SetV_NotExist)) int V3; + __declspec(property(get=GetV_NotExist, put=SetV)) int V4; + __declspec(property(get=GetV, put=SetV)) int V5; + + int GetV() { return 123; } + void SetV(int i) {} +}; +void TestProperty() { + StructWithProperty sp; + int i = sp.V2; // expected-error{{no getter defined for property 'V2'}} + sp.V1 = 12; // expected-error{{no setter defined for property 'V1'}} + int j = sp.V4; // expected-error{{no member named 'GetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable getter for property 'V4'}} + sp.V3 = 14; // expected-error{{no member named 'SetV_NotExist' in 'StructWithProperty'}} expected-error{{cannot find suitable setter for property 'V3'}} + int k = sp.V5; + sp.V5 = k++; +} + +/* 4 tests for PseudoObject, begin */ +struct SP1 +{ + bool operator()() { return true; } +}; +struct SP2 +{ + __declspec(property(get=GetV)) SP1 V; + SP1 GetV() { return SP1(); } +}; +void TestSP2() { + SP2 sp2; + bool b = sp2.V(); +} + +struct SP3 { + template <class T> + void f(T t) {} +}; +template <class T> +struct SP4 +{ + __declspec(property(get=GetV)) int V; + int GetV() { return 123; } + void f() { SP3 s2; s2.f(V); } +}; +void TestSP4() { + SP4<int> s; + s.f(); +} + +template <class T> +struct SP5 +{ + __declspec(property(get=GetV)) T V; + int GetV() { return 123; } + void f() { int *p = new int[V]; } +}; + +template <class T> +struct SP6 +{ +public: + __declspec(property(get=GetV)) T V; + T GetV() { return 123; } + void f() { int t = V; } +}; +void TestSP6() { + SP6<int> c; + c.f(); +} +/* 4 tests for PseudoObject, end */ + +// Property access: explicit, implicit, with Qualifier +struct SP7 { + __declspec(property(get=GetV, put=SetV)) int V; + int GetV() { return 123; } + void SetV(int v) {} + + void ImplicitAccess() { int i = V; V = i; } + void ExplicitAccess() { int i = this->V; this->V = i; } +}; +struct SP8: public SP7 { + void AccessWithQualifier() { int i = SP7::V; SP7::V = i; } +}; + +// Property usage +template <class T> +struct SP9 { + __declspec(property(get=GetV, put=SetV)) T V; + T GetV() { return 0; } + void SetV(T v) {} + void f() { V = this->V; V < this->V; } + void g() { V++; } + void h() { V*=2; } +}; +struct SP10 { + SP10(int v) {} + bool operator<(const SP10& v) { return true; } + SP10 operator*(int v) { return *this; } + SP10 operator+(int v) { return *this; } + SP10& operator=(const SP10& v) { return *this; } +}; +void TestSP9() { + SP9<int> c; + int i = c.V; // Decl initializer + i = c.V; // Binary op operand + c.SetV(c.V); // CallExpr arg + int *p = new int[c.V + 1]; // Array size + p[c.V] = 1; // Array index + + c.V = 123; // Setter + + c.V++; // Unary op operand + c.V *= 2; // Unary op operand + + SP9<int*> c2; + c2.V[0] = 123; // Array + + SP9<SP10> c3; + c3.f(); // Overloaded binary op operand + c3.g(); // Overloaded incdec op operand + c3.h(); // Overloaded unary op operand +} diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index 18ad301..50f2eff 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s class C { struct S; // expected-note {{previously declared 'private' here}} @@ -32,3 +32,77 @@ namespace test1 { class X {}; }; } + +// PR15209 +namespace PR15209 { + namespace alias_templates { + template<typename T1, typename T2> struct U { }; + template<typename T1> using W = U<T1, float>; + + class A { + typedef int I; + static constexpr I x = 0; // expected-note {{implicitly declared private here}} + static constexpr I y = 42; // expected-note {{implicitly declared private here}} + friend W<int>; + }; + + template<typename T1> + struct U<T1, float> { + int v_; + // the following will trigger for U<float, float> instantiation, via W<float> + U() : v_(A::x) { } // expected-error {{'x' is a private member of 'PR15209::alias_templates::A'}} + }; + + template<typename T1> + struct U<T1, int> { + int v_; + U() : v_(A::y) { } // expected-error {{'y' is a private member of 'PR15209::alias_templates::A'}} + }; + + template struct U<int, int>; // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<int, int>::U' requested here}} + + void f() + { + W<int>(); + // we should issue diagnostics for the following + W<float>(); // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<float, float>::U' requested here}} + } + } + + namespace templates { + class A { + typedef int I; // expected-note {{implicitly declared private here}} + static constexpr I x = 0; // expected-note {{implicitly declared private here}} + + template<int> friend struct B; + template<int> struct C; + template<template<int> class T> friend struct TT; + template<typename T> friend void funct(T); + }; + template<A::I> struct B { }; + + template<A::I> struct A::C { }; + + template<template<A::I> class T> struct TT { + T<A::x> t; + }; + + template struct TT<B>; + template<A::I> struct D { }; // expected-error {{'I' is a private member of 'PR15209::templates::A'}} + template struct TT<D>; + + // function template case + template<typename T> + void funct(T) + { + (void)A::x; + } + + template void funct<int>(int); + + void f() + { + (void)A::x; // expected-error {{'x' is a private member of 'PR15209::templates::A'}} + } + } +} diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp new file mode 100644 index 0000000..a9de1ad --- /dev/null +++ b/test/SemaCXX/alignof.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// rdar://13784901 + +struct S0 { + int x; + static const int test0 = __alignof__(x); // expected-error {{invalid application of 'alignof' to a field of a class still being defined}} + static const int test1 = __alignof__(S0::x); // expected-error {{invalid application of 'alignof' to a field of a class still being defined}} + auto test2() -> char(&)[__alignof__(x)]; // expected-error {{invalid application of 'alignof' to a field of a class still being defined}} +}; + +struct S1; // expected-note 5 {{forward declaration}} +extern S1 s1; +const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + +struct S2 { + S2(); + S1 &s; + int x; + + int test4 = __alignof__(x); // ok + int test5 = __alignof__(s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} +}; + +const int test6 = __alignof__(S2::x); +const int test7 = __alignof__(S2::s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + +// Arguably, these should fail like the S1 cases do: the alignment of +// 's2.x' should depend on the alignment of both x-within-S2 and +// s2-within-S3 and thus require 'S3' to be complete. If we start +// doing the appropriate recursive walk to do that, we should make +// sure that these cases don't explode. +struct S3 { + S2 s2; + + static const int test8 = __alignof__(s2.x); + static const int test9 = __alignof__(s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + auto test10() -> char(&)[__alignof__(s2.x)]; + static const int test11 = __alignof__(S3::s2.x); + static const int test12 = __alignof__(S3::s2.s); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} + auto test13() -> char(&)[__alignof__(s2.x)]; +}; + +// Same reasoning as S3. +struct S4 { + union { + int x; + }; + static const int test0 = __alignof__(x); + static const int test1 = __alignof__(S0::x); + auto test2() -> char(&)[__alignof__(x)]; +}; diff --git a/test/SemaCXX/ast-print.cpp b/test/SemaCXX/ast-print.cpp index 5de8c4b..921f7d8 100644 --- a/test/SemaCXX/ast-print.cpp +++ b/test/SemaCXX/ast-print.cpp @@ -137,3 +137,14 @@ void test12() { ConstrWithCleanupsClass cwcExplicitArg(VirualDestrClass(56)); } +// CHECK: void test13() { +// CHECK: _Atomic(int) i; +// CHECK: __c11_atomic_init(&i, 0); +// CHECK: __c11_atomic_load(&i, 0); +// CHECK: } +void test13() { + _Atomic(int) i; + __c11_atomic_init(&i, 0); + __c11_atomic_load(&i, 0); +} + diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp index f3d548b..41214c4 100644 --- a/test/SemaCXX/attr-noreturn.cpp +++ b/test/SemaCXX/attr-noreturn.cpp @@ -80,3 +80,86 @@ namespace PR12948 { template<typename> void wibble() __attribute__((__noreturn__)); template<typename> voidfn wibble; } + +// PR15291 +// Overload resolution per over.over should allow implicit noreturn adjustment. +namespace PR15291 { + __attribute__((noreturn)) void foo(int) {} + __attribute__((noreturn)) void foo(double) {} + + template <typename T> + __attribute__((noreturn)) void bar(T) {} + + void baz(int) {} + void baz(double) {} + + template <typename T> + void qux(T) {} + + // expected-note@+5 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+4 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+3 {{candidate function [with T = void (*)(int) __attribute__((noreturn))] not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+2 {{candidate function [with T = void (*)(int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} + // expected-note@+1 {{candidate function [with T = void (int)] not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} + template <typename T> void accept_T(T) {} + + // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} + void accept_fptr(void (*f)(int)) { + f(42); + } + + // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} + void accept_noreturn_fptr(void __attribute__((noreturn)) (*f)(int)) { + f(42); + } + + typedef void (*fptr_t)(int); + typedef void __attribute__((noreturn)) (*fptr_noreturn_t)(int); + + // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'fptr_t' (aka 'void (*)(int)') for 1st argument}} + void accept_fptr_t(fptr_t f) { + f(42); + } + + // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}} + // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}} + void accept_fptr_noreturn_t(fptr_noreturn_t f) { + f(42); + } + + // Stripping noreturn should work if everything else is correct. + void strip_noreturn() { + accept_fptr(foo); + accept_fptr(bar<int>); + accept_fptr(bar<double>); // expected-error {{no matching function for call to 'accept_fptr'}} + + accept_fptr_t(foo); + accept_fptr_t(bar<int>); + accept_fptr_t(bar<double>); // expected-error {{no matching function for call to 'accept_fptr_t'}} + + accept_T<void __attribute__((noreturn)) (*)(int)>(foo); + accept_T<void __attribute__((noreturn)) (*)(int)>(bar<int>); + accept_T<void __attribute__((noreturn)) (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}} + + accept_T<void (*)(int)>(foo); + accept_T<void (*)(int)>(bar<int>); + accept_T<void (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}} + + accept_T<void (int)>(foo); + accept_T<void (int)>(bar<int>); + accept_T<void (int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}} + } + + // Introducing noreturn should not work. + void introduce_noreturn() { + accept_noreturn_fptr(baz); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}} + accept_noreturn_fptr(qux<int>); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}} + + accept_fptr_noreturn_t(baz); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}} + accept_fptr_noreturn_t(qux<int>); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}} + + accept_T<void __attribute__((noreturn)) (*)(int)>(baz); // expected-error {{no matching function for call to 'accept_T'}} + accept_T<void __attribute__((noreturn)) (*)(int)>(qux<int>); // expected-error {{no matching function for call to 'accept_T'}} + } +} diff --git a/test/SemaCXX/captured-statements.cpp b/test/SemaCXX/captured-statements.cpp new file mode 100644 index 0000000..dbb18a7 --- /dev/null +++ b/test/SemaCXX/captured-statements.cpp @@ -0,0 +1,166 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -fblocks + +void test_nest_lambda() { + int x; + int y; + [&,y]() { + int z; + #pragma clang __debug captured + { + x = y; // OK + y = z; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}} + z = y; // OK + } + }(); + + int a; + #pragma clang __debug captured + { + int b; + int c; + [&,c]() { + a = b; // OK + b = c; // OK + c = a; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}} + }(); + } +} + +class test_obj_capture { + int a; + void b(); + static void test() { + test_obj_capture c; + #pragma clang __debug captured + { (void)c.a; } // OK + #pragma clang __debug captured + { c.b(); } // OK + } +}; + +class test_this_capture { + int a; + void b(); + void test() { + #pragma clang __debug captured + { (void)this; } // OK + #pragma clang __debug captured + { (void)a; } // OK + #pragma clang __debug captured + { b(); } // OK + } +}; + +template <typename T> +void template_capture_var() { + T x; // expected-error{{declaration of reference variable 'x' requires an initializer}} + #pragma clang _debug captured + { + (void)x; + } +} + +template <typename T> +class Val { + T v; +public: + void set(const T &v0) { + #pragma clang __debug captured + { + v = v0; + } + } +}; + +void test_capture_var() { + template_capture_var<int>(); // OK + template_capture_var<int&>(); // expected-note{{in instantiation of function template specialization 'template_capture_var<int &>' requested here}} + + Val<float> Obj; + Obj.set(0.0f); // OK +} + +template <typename S, typename T> +S template_capture_var(S x, T y) { + #pragma clang _debug captured + { + x++; + y++; // expected-error{{read-only variable is not assignable}} + } + + return x; +} + +// Check if can recover from a template error. +void test_capture_var_error() { + template_capture_var<int, int>(0, 1); // OK + template_capture_var<int, const int>(0, 1); // expected-note{{in instantiation of function template specialization 'template_capture_var<int, const int>' requested here}} + template_capture_var<int, int>(0, 1); // OK +} + +template <typename T> +void template_capture_in_lambda() { + T x, y; + [=, &y]() { + #pragma clang __debug captured + { + y += x; + } + }(); +} + +void test_lambda() { + template_capture_in_lambda<int>(); // OK +} + +struct Foo { + void foo() { } + static void bar() { } +}; + +template <typename T> +void template_capture_func(T &t) { + #pragma clang __debug captured + { + t.foo(); + } + + #pragma clang __debug captured + { + T::bar(); + } +} + +void test_template_capture_func() { + Foo Obj; + template_capture_func(Obj); +} + +template <typename T> +T captured_sum(const T &a, const T &b) { + T result; + + #pragma clang __debug captured + { + result = a + b; + } + + return result; +} + +template <typename T, typename... Args> +T captured_sum(const T &a, const Args&... args) { + T result; + + #pragma clang __debug captured + { + result = a + captured_sum(args...); + } + + return result; +} + +void test_capture_variadic() { + (void)captured_sum(1, 2, 3); // OK + (void)captured_sum(1, 2, 3, 4, 5); // OK +} diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp index fe0e45d..595747e 100644 --- a/test/SemaCXX/compound-literal.cpp +++ b/test/SemaCXX/compound-literal.cpp @@ -1,4 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03 +// RUN: FileCheck --input-file=%t-03 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11 +// RUN: FileCheck --input-file=%t-11 %s +// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11 // http://llvm.org/PR7905 namespace PR7905 { @@ -12,3 +16,63 @@ void foo2() { (void)(M<short> []) {{3}}; } } + +// Check compound literals mixed with C++11 list-initialization. +namespace brace_initializers { + struct POD { + int x, y; + }; + struct HasCtor { + HasCtor(int x, int y); + }; + struct HasDtor { + int x, y; + ~HasDtor(); + }; + struct HasCtorDtor { + HasCtorDtor(int x, int y); + ~HasCtorDtor(); + }; + + void test() { + (void)(POD){1, 2}; + // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::POD' + // CHECK: CompoundLiteralExpr {{.*}} 'struct brace_initializers::POD' + // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::POD' + // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}} + // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}} + + (void)(HasDtor){1, 2}; + // CHECK: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasDtor' + // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasDtor' + // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::HasDtor' + // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}} + // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}} + +#if __cplusplus >= 201103L + (void)(HasCtor){1, 2}; + // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtor' + // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtor' + // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtor' + // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}} + // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}} + + (void)(HasCtorDtor){1, 2}; + // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtorDtor' + // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtorDtor' + // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtorDtor' + // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}} + // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}} +#endif + } + + struct PrivateDtor { + int x, y; + private: + ~PrivateDtor(); // expected-note {{declared private here}} + }; + + void testPrivateDtor() { + (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}} + } +} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index d805881..73f3dce 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s void test() { int x; @@ -6,7 +6,7 @@ void test() { if (int x=0) ++x; typedef int arr[10]; - while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}} + while (arr x={0}) ; // expected-error {{an array type is not allowed here}} while (int f()=0) ; // expected-error {{a function type is not allowed here}} struct S {} s; @@ -19,9 +19,7 @@ void test() { while (struct NewS *x=0) ; while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}} while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}} - switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} \ - // expected-warning{{enumeration value 'E' not handled in switch}} expected-warning {{switch statement has empty body}} \ - // expected-note{{put the semicolon on a separate line}} + switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} if (int x=0) { // expected-note 2 {{previous definition is here}} int x; // expected-error {{redefinition of 'x'}} diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 30aa7d7..09a9cb5 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -21,7 +21,7 @@ template<typename T, size_t N> constexpr T *begin(T (&xs)[N]) { return xs; } template<typename T, size_t N> constexpr T *end(T (&xs)[N]) { return xs + N; } struct MemberZero { - constexpr int zero() { return 0; } + constexpr int zero() const { return 0; } }; namespace DerivedToVBaseCast { @@ -304,16 +304,16 @@ struct Str { expected-note {{reinterpret_cast is not allowed in a constant expression}} int c : (S*)(long)(sptr) == (S*)(long)(sptr); // \ expected-warning {{not an integral constant expression}} \ - expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} int d : (S*)(42) == (S*)(42); // \ expected-warning {{not an integral constant expression}} \ - expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} int e : (Str*)(sptr) == (Str*)(sptr); // \ expected-warning {{not an integral constant expression}} \ - expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} int f : &(U&)(*sptr) == &(U&)(*sptr); // \ expected-warning {{not an integral constant expression}} \ - expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} int g : (S*)(void*)(sptr) == sptr; // \ expected-warning {{not an integral constant expression}} \ expected-note {{cast from 'void *' is not allowed in a constant expression}} @@ -362,7 +362,7 @@ constexpr char c0 = "nought index"[0]; constexpr char c1 = "nice index"[10]; constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}} expected-note {{read of dereferenced one-past-the-end pointer}} constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}} expected-note {{cannot refer to element -1 of array of 15 elements}} -constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast which performs the conversions of a reinterpret_cast}} +constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast that performs the conversions of a reinterpret_cast}} constexpr const char *p = "test" + 2; static_assert(*p == 's', ""); @@ -414,6 +414,19 @@ struct V { }; static_assert(V().c[1] == "i"[0], ""); +namespace Parens { + constexpr unsigned char a[] = ("foo"), b[] = {"foo"}, c[] = {("foo")}, + d[4] = ("foo"), e[5] = {"foo"}, f[6] = {("foo")}; + static_assert(a[0] == 'f', ""); + static_assert(b[1] == 'o', ""); + static_assert(c[2] == 'o', ""); + static_assert(d[0] == 'f', ""); + static_assert(e[1] == 'o', ""); + static_assert(f[2] == 'o', ""); + static_assert(f[5] == 0, ""); + static_assert(f[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}} +} + } namespace Array { @@ -486,7 +499,7 @@ static_assert(CountZero(arr, arr + 40) == 36, ""); struct ArrayElem { constexpr ArrayElem() : n(0) {} int n; - constexpr int f() { return n; } + constexpr int f() const { return n; } }; struct ArrayRVal { constexpr ArrayRVal() {} @@ -731,14 +744,14 @@ namespace ConversionOperators { struct T { constexpr T(int n) : k(5*n - 3) {} - constexpr operator int() { return k; } + constexpr operator int() const { return k; } int k; }; struct S { constexpr S(int n) : k(2*n + 1) {} - constexpr operator int() { return k; } - constexpr operator T() { return T(k); } + constexpr operator int() const { return k; } + constexpr operator T() const { return T(k); } int k; }; @@ -750,7 +763,7 @@ static_assert(check(S(5), 11), ""); namespace PR14171 { struct X { - constexpr (operator int)() { return 0; } + constexpr (operator int)() const { return 0; } }; static_assert(X() == 0, ""); @@ -764,13 +777,13 @@ namespace Temporaries { struct S { constexpr S() {} - constexpr int f(); + constexpr int f() const; }; struct T : S { constexpr T(int n) : S(), n(n) {} int n; }; -constexpr int S::f() { +constexpr int S::f() const { // 'this' must be the postfix-expression in a class member access expression, // so we can't just use // return static_cast<T*>(this)->n; @@ -825,7 +838,7 @@ namespace MemberPointer { struct A { constexpr A(int n) : n(n) {} int n; - constexpr int f() { return n + 3; } + constexpr int f() const { return n + 3; } }; constexpr A a(7); static_assert(A(5).*&A::n == 5, ""); @@ -836,7 +849,7 @@ namespace MemberPointer { struct B : A { constexpr B(int n, int m) : A(n), m(m) {} int m; - constexpr int g() { return n + m + 1; } + constexpr int g() const { return n + m + 1; } }; constexpr B b(9, 13); static_assert(B(4, 11).*&A::n == 4, ""); @@ -857,7 +870,7 @@ namespace MemberPointer { m(m), n(n), pf(pf), pn(pn) {} constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {} - constexpr int f() { return this->*pn; } + constexpr int f() const { return this->*pn; } virtual int g() const; int m, n; @@ -938,7 +951,7 @@ namespace ArrayBaseDerived { }; struct Derived : Base { constexpr Derived() {} - constexpr const int *f() { return &n; } + constexpr const int *f() const { return &n; } }; constexpr Derived a[10]; @@ -1038,7 +1051,7 @@ static_assert(makeComplexWrap(1,0) != complex(0, 1), ""); } namespace PR11595 { - struct A { constexpr bool operator==(int x) { return true; } }; + struct A { constexpr bool operator==(int x) const { return true; } }; struct B { B(); A& x; }; static_assert(B().x == 3, ""); // expected-error {{constant expression}} expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}} @@ -1312,6 +1325,13 @@ namespace InvalidClasses { } } +namespace NamespaceAlias { + constexpr int f() { + namespace NS = NamespaceAlias; // expected-warning {{use of this statement in a constexpr function is a C++1y extension}} + return &NS::f != nullptr; + } +} + // Constructors can be implicitly constexpr, even for a non-literal type. namespace ImplicitConstexpr { struct Q { Q() = default; Q(const Q&) = default; Q(Q&&) = default; ~Q(); }; // expected-note 3{{here}} @@ -1455,3 +1475,31 @@ namespace PR14203 { // constructor here. int n = sizeof(short{duration(duration())}); } + +namespace ArrayEltInit { + struct A { + constexpr A() : p(&p) {} + void *p; + }; + constexpr A a[10]; + static_assert(a[0].p == &a[0].p, ""); + static_assert(a[9].p == &a[9].p, ""); + static_assert(a[0].p != &a[9].p, ""); + static_assert(a[9].p != &a[0].p, ""); + + constexpr A b[10] = {}; + static_assert(b[0].p == &b[0].p, ""); + static_assert(b[9].p == &b[9].p, ""); + static_assert(b[0].p != &b[9].p, ""); + static_assert(b[9].p != &b[0].p, ""); +} + +namespace PR15884 { + struct S {}; + constexpr S f() { return {}; } + constexpr S *p = &f(); + // expected-error@-1 {{taking the address of a temporary}} + // expected-error@-2 {{constexpr variable 'p' must be initialized by a constant expression}} + // expected-note@-3 {{pointer to temporary is not a constant expression}} + // expected-note@-4 {{temporary created here}} +} diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp new file mode 100644 index 0000000..60ec820 --- /dev/null +++ b/test/SemaCXX/constant-expression-cxx1y.cpp @@ -0,0 +1,459 @@ +// RUN: %clang_cc1 -std=c++1y -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu + +struct S { + // dummy ctor to make this a literal type + constexpr S(int); + + S(); + + int arr[10]; + + constexpr int &get(int n) { return arr[n]; } + constexpr const int &get(int n) const { return arr[n]; } +}; + +S s = S(); +const S &sr = s; +static_assert(&s.get(4) - &sr.get(2) == 2, ""); + +// Compound-statements can be used in constexpr functions. +constexpr int e() {{{{}} return 5; }} +static_assert(e() == 5, ""); + +// Types can be defined in constexpr functions. +constexpr int f() { + enum E { e1, e2, e3 }; + + struct S { + constexpr S(E e) : e(e) {} + constexpr int get() { return e; } + E e; + }; + + return S(e2).get(); +} +static_assert(f() == 1, ""); + +// Variables can be declared in constexpr functions. +constexpr int g(int k) { + const int n = 9; + int k2 = k * k; + int k3 = k2 * k; + return 3 * k3 + 5 * k2 + n * k - 20; +} +static_assert(g(2) == 42, ""); +constexpr int h(int n) { + static const int m = n; // expected-error {{static variable not permitted in a constexpr function}} + return m; +} +constexpr int i(int n) { + thread_local const int m = n; // expected-error {{thread_local variable not permitted in a constexpr function}} + return m; +} + +// if-statements can be used in constexpr functions. +constexpr int j(int k) { + if (k == 5) + return 1; + if (k == 1) + return 5; + else { + if (int n = 2 * k - 4) { + return n + 1; + return 2; + } + } +} // expected-note 2{{control reached end of constexpr function}} +static_assert(j(0) == -3, ""); +static_assert(j(1) == 5, ""); +static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}} +static_assert(j(3) == 3, ""); +static_assert(j(4) == 5, ""); +static_assert(j(5) == 1, ""); + +// There can be 0 return-statements. +constexpr void k() { +} + +// If the return type is not 'void', no return statements => never a constant +// expression, so still diagnose that case. +[[noreturn]] constexpr int fn() { // expected-error {{no return statement in constexpr function}} + fn(); +} + +// We evaluate the body of a constexpr constructor, to check for side-effects. +struct U { + constexpr U(int n) { + if (j(n)) {} // expected-note {{in call to 'j(2)'}} + } +}; +constexpr U u1{1}; +constexpr U u2{2}; // expected-error {{constant expression}} expected-note {{in call to 'U(2)'}} + +// We allow expression-statements. +constexpr int l(bool b) { + if (b) + throw "invalid value for b!"; // expected-note {{subexpression not valid}} + return 5; +} +static_assert(l(false) == 5, ""); +static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}} + +// Potential constant expression checking is still applied where possible. +constexpr int htonl(int x) { // expected-error {{never produces a constant expression}} + typedef unsigned char uchar; + uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) }; + return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} +} + +constexpr int maybe_htonl(bool isBigEndian, int x) { + if (isBigEndian) + return x; + + typedef unsigned char uchar; + uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) }; + return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} +} + +constexpr int swapped = maybe_htonl(false, 123); // expected-error {{constant expression}} expected-note {{in call}} + +namespace NS { + constexpr int n = 0; +} +constexpr int namespace_alias() { + namespace N = NS; + return N::n; +} + +namespace assign { + constexpr int a = 0; + const int b = 0; + int c = 0; // expected-note 2{{here}} + + constexpr void set(const int &a, int b) { + const_cast<int&>(a) = b; // expected-note 2{{constant expression cannot modify an object that is visible outside that expression}} + } + constexpr int wrap(int a, int b) { + set(a, b); + return a; + } + + static_assert((set(a, 1), a) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(a, 1)'}} + static_assert((set(b, 1), b) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(b, 1)'}} + static_assert((set(c, 1), c) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + + static_assert(wrap(a, 1) == 1, ""); + static_assert(wrap(b, 1) == 1, ""); + static_assert(wrap(c, 1) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} +} + +namespace string_assign { + template<typename T> + constexpr void swap(T &a, T &b) { + T tmp = a; + a = b; + b = tmp; + } + template<typename Iterator> + constexpr void reverse(Iterator begin, Iterator end) { + while (begin != end && begin != --end) + swap(*begin++, *end); + } + template<typename Iterator1, typename Iterator2> + constexpr bool equal(Iterator1 a, Iterator1 ae, Iterator2 b, Iterator2 be) { + while (a != ae && b != be) + if (*a++ != *b++) + return false; + return a == ae && b == be; + } + constexpr bool test1(int n) { + char stuff[100] = "foobarfoo"; + const char stuff2[100] = "oofraboof"; + reverse(stuff, stuff + n); // expected-note {{cannot refer to element 101 of array of 100 elements}} + return equal(stuff, stuff + n, stuff2, stuff2 + n); + } + static_assert(!test1(1), ""); + static_assert(test1(3), ""); + static_assert(!test1(6), ""); + static_assert(test1(9), ""); + static_assert(!test1(100), ""); + static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}} + + // FIXME: We should be able to reject this before it's called + constexpr void f() { + char foo[10] = { "z" }; // expected-note {{here}} + foo[10] = 'x'; // expected-warning {{past the end}} expected-note {{assignment to dereferenced one-past-the-end pointer}} + } + constexpr int k = (f(), 0); // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace array_resize { + constexpr int do_stuff(int k1, int k2) { + int arr[1234] = { 1, 2, 3, 4 }; + arr[k1] = 5; // expected-note {{past-the-end}} expected-note {{cannot refer to element 1235}} expected-note {{cannot refer to element -1}} + return arr[k2]; + } + static_assert(do_stuff(1, 2) == 3, ""); + static_assert(do_stuff(0, 0) == 5, ""); + static_assert(do_stuff(1233, 1233) == 5, ""); + static_assert(do_stuff(1233, 0) == 1, ""); + static_assert(do_stuff(1234, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(do_stuff(1235, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(do_stuff(-1, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace potential_const_expr { + constexpr void set(int &n) { n = 1; } + constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error + constexpr int div_zero_2() { // expected-error {{never produces a constant expression}} + int z = 0; + return 100 / (set(z), 0); // expected-note {{division by zero}} + } + int n; // expected-note {{declared here}} + constexpr int ref() { // expected-error {{never produces a constant expression}} + int &r = n; + return r; // expected-note {{read of non-const variable 'n'}} + } +} + +namespace subobject { + union A { constexpr A() : y(5) {} int x, y; }; + struct B { A a; }; + struct C : B {}; + union D { constexpr D() : c() {} constexpr D(int n) : n(n) {} C c; int n; }; + constexpr void f(D &d) { + d.c.a.y = 3; + // expected-note@-1 {{cannot modify an object that is visible outside}} + // expected-note@-2 {{assignment to member 'c' of union with active member 'n'}} + } + constexpr bool check(D &d) { return d.c.a.y == 3; } + + constexpr bool g() { D d; f(d); return d.c.a.y == 3; } + static_assert(g(), ""); + + D d; + constexpr bool h() { f(d); return check(d); } // expected-note {{in call}} + static_assert(h(), ""); // expected-error {{constant expression}} expected-note {{in call}} + + constexpr bool i() { D d(0); f(d); return check(d); } // expected-note {{in call}} + static_assert(i(), ""); // expected-error {{constant expression}} expected-note {{in call}} + + constexpr bool j() { D d; d.c.a.x = 3; return check(d); } // expected-note {{assignment to member 'x' of union with active member 'y'}} + static_assert(j(), ""); // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace lifetime { + constexpr int &&id(int &&n) { return static_cast<int&&>(n); } + constexpr int &&dead() { return id(0); } // expected-note {{temporary created here}} + constexpr int bad() { int &&n = dead(); n = 1; return n; } // expected-note {{assignment to temporary whose lifetime has ended}} + static_assert(bad(), ""); // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace const_modify { + constexpr int modify(int &n) { return n = 1; } // expected-note {{modification of object of const-qualified type 'const int'}} + constexpr int test1() { int k = 0; return modify(k); } + constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note {{in call}} + static_assert(test1() == 1, ""); + static_assert(test2() == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace null { + constexpr int test(int *p) { + return *p = 123; // expected-note {{assignment to dereferenced null pointer}} + } + static_assert(test(0), ""); // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace incdec { + template<typename T> constexpr T &ref(T &&r) { return r; } + template<typename T> constexpr T postinc(T &&r) { return (r++, r); } + template<typename T> constexpr T postdec(T &&r) { return (r--, r); } + + static_assert(++ref(0) == 1, ""); + static_assert(ref(0)++ == 0, ""); + static_assert(postinc(0) == 1, ""); + static_assert(--ref(0) == -1, ""); + static_assert(ref(0)-- == 0, ""); + static_assert(postdec(0) == -1, ""); + + constexpr int overflow_int_inc_1 = ref(0x7fffffff)++; // expected-error {{constant}} expected-note {{2147483648}} + constexpr int overflow_int_inc_1_ok = ref(0x7ffffffe)++; + constexpr int overflow_int_inc_2 = ++ref(0x7fffffff); // expected-error {{constant}} expected-note {{2147483648}} + constexpr int overflow_int_inc_2_ok = ++ref(0x7ffffffe); + + // inc/dec on short can't overflow because we promote to int first + static_assert(++ref<short>(0x7fff) == (int)0xffff8000u, ""); + static_assert(--ref<short>(0x8000) == 0x7fff, ""); + + // inc on bool sets to true + static_assert(++ref(false), ""); // expected-warning {{deprecated}} + static_assert(++ref(true), ""); // expected-warning {{deprecated}} + + int arr[10]; + static_assert(++ref(&arr[0]) == &arr[1], ""); + static_assert(++ref(&arr[9]) == &arr[10], ""); + static_assert(++ref(&arr[10]) == &arr[11], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}} + static_assert(ref(&arr[0])++ == &arr[0], ""); + static_assert(ref(&arr[10])++ == &arr[10], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}} + static_assert(postinc(&arr[0]) == &arr[1], ""); + static_assert(--ref(&arr[10]) == &arr[9], ""); + static_assert(--ref(&arr[1]) == &arr[0], ""); + static_assert(--ref(&arr[0]) != &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}} + static_assert(ref(&arr[1])-- == &arr[1], ""); + static_assert(ref(&arr[0])-- == &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}} + static_assert(postdec(&arr[1]) == &arr[0], ""); + + int x; + static_assert(++ref(&x) == &x + 1, ""); + + static_assert(++ref(0.0) == 1.0, ""); + static_assert(ref(0.0)++ == 0.0, ""); + static_assert(postinc(0.0) == 1.0, ""); + static_assert(--ref(0.0) == -1.0, ""); + static_assert(ref(0.0)-- == 0.0, ""); + static_assert(postdec(0.0) == -1.0, ""); + + static_assert(++ref(1e100) == 1e100, ""); + static_assert(--ref(1e100) == 1e100, ""); + + union U { + int a, b; + }; + constexpr int f(U u) { + return ++u.b; // expected-note {{increment of member 'b' of union with active member 'a'}} + } + constexpr int wrong_member = f({0}); // expected-error {{constant}} expected-note {{in call to 'f({.a = 0})'}} + constexpr int vol = --ref<volatile int>(0); // expected-error {{constant}} expected-note {{decrement of volatile-qualified}} + + constexpr int incr(int k) { + int x = k; + if (x++ == 100) + return x; + return incr(x); + } + static_assert(incr(0) == 101, ""); +} + +namespace loops { + constexpr int fib_loop(int a) { + int f_k = 0, f_k_plus_one = 1; + for (int k = 1; k != a; ++k) { + int f_k_plus_two = f_k + f_k_plus_one; + f_k = f_k_plus_one; + f_k_plus_one = f_k_plus_two; + } + return f_k_plus_one; + } + static_assert(fib_loop(46) == 1836311903, ""); + + constexpr bool breaks_work() { + int a = 0; + for (int n = 0; n != 100; ++n) { + ++a; + if (a == 5) continue; + if ((a % 5) == 0) break; + } + + int b = 0; + while (b != 17) { + ++b; + if (b == 6) continue; + if ((b % 6) == 0) break; + } + + int c = 0; + do { + ++c; + if (c == 7) continue; + if ((c % 7) == 0) break; + } while (c != 21); + + return a == 10 && b == 12 & c == 14; + } + static_assert(breaks_work(), ""); + + void not_constexpr(); + constexpr bool no_cont_after_break() { + for (;;) { + break; + not_constexpr(); + } + while (true) { + break; + not_constexpr(); + } + do { + break; + not_constexpr(); + } while (true); + return true; + } + static_assert(no_cont_after_break(), ""); + + constexpr bool cond() { + for (int a = 1; bool b = a != 3; ++a) { + if (!b) + return false; + } + while (bool b = true) { + b = false; + break; + } + return true; + } + static_assert(cond(), ""); + + constexpr int range_for() { + int arr[] = { 1, 2, 3, 4, 5 }; + int sum = 0; + for (int x : arr) + sum = sum + x; + return sum; + } + static_assert(range_for() == 15, ""); + + template<int...N> struct ints {}; + template<typename A, typename B> struct join_ints; + template<int...As, int...Bs> struct join_ints<ints<As...>, ints<Bs...>> { + using type = ints<As..., sizeof...(As) + Bs...>; + }; + template<unsigned N> struct make_ints { + using type = typename join_ints<typename make_ints<N/2>::type, typename make_ints<(N+1)/2>::type>::type; + }; + template<> struct make_ints<0> { using type = ints<>; }; + template<> struct make_ints<1> { using type = ints<0>; }; + + struct ignore { template<typename ...Ts> constexpr ignore(Ts &&...) {} }; + + template<typename T, unsigned N> struct array { + constexpr array() : arr{} {} + template<typename ...X> + constexpr array(X ...x) : arr{} { + init(typename make_ints<sizeof...(X)>::type{}, x...); + } + template<int ...I, typename ...X> constexpr void init(ints<I...>, X ...x) { + ignore{arr[I] = x ...}; + } + T arr[N]; + struct iterator { + T *p; + constexpr explicit iterator(T *p) : p(p) {} + constexpr bool operator!=(iterator o) { return p != o.p; } + constexpr iterator &operator++() { ++p; return *this; } + constexpr T &operator*() { return *p; } + }; + constexpr iterator begin() { return iterator(arr); } + constexpr iterator end() { return iterator(arr + N); } + }; + + constexpr int range_for_2() { + array<int, 5> arr { 1, 2, 3, 4, 5 }; + int sum = 0; + for (int k : arr) { + sum = sum + k; + if (sum > 8) break; + } + return sum; + } + static_assert(range_for_2() == 10, ""); +} diff --git a/test/SemaCXX/constexpr-printing.cpp b/test/SemaCXX/constexpr-printing.cpp index 9170fa1..e545f45 100644 --- a/test/SemaCXX/constexpr-printing.cpp +++ b/test/SemaCXX/constexpr-printing.cpp @@ -9,7 +9,7 @@ struct S { int n, m; }; -constexpr int extract(const S &s) { return s.n; } // expected-note {{read of uninitialized object is not allowed in a constant expression}} +constexpr int extract(const S &s) { return s.n; } // expected-note {{read of object outside its lifetime is not allowed in a constant expression}} constexpr S s1; // ok void f() { diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp index e459f09..d137bd8 100644 --- a/test/SemaCXX/constexpr-value-init.cpp +++ b/test/SemaCXX/constexpr-value-init.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify struct A { - constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{uninitialized}} + constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{outside its lifetime}} int a; int b; }; diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp index f95eeb5..f7bfc11 100644 --- a/test/SemaCXX/cxx11-ast-print.cpp +++ b/test/SemaCXX/cxx11-ast-print.cpp @@ -41,3 +41,5 @@ const char *p10 = 3.300e+15_fritz; // CHECK: ; ; // CHECK-NOT: ; + + diff --git a/test/SemaCXX/cxx11-crashes.cpp b/test/SemaCXX/cxx11-crashes.cpp index bd51af1..a4d4829 100644 --- a/test/SemaCXX/cxx11-crashes.cpp +++ b/test/SemaCXX/cxx11-crashes.cpp @@ -70,7 +70,9 @@ namespace b6981007 { for (auto x : s) { // We used to attempt to evaluate the initializer of this variable, // and crash because it has an undeduced type. - const int &n(x); + // FIXME: We should set the loop variable to be invalid if we can't build + // the loop, to suppress this follow-on error. + const int &n(x); // expected-error {{could not bind to an lvalue of type 'auto'}} } } } diff --git a/test/SemaCXX/cxx11-inheriting-ctors.cpp b/test/SemaCXX/cxx11-inheriting-ctors.cpp new file mode 100644 index 0000000..67d5521 --- /dev/null +++ b/test/SemaCXX/cxx11-inheriting-ctors.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +// expected-no-diagnostics + +namespace PR15757 { + struct S { + }; + + template<typename X, typename Y> struct T { + template<typename A> T(X x, A &&a) {} + + template<typename A> explicit T(A &&a) + noexcept(noexcept(T(X(), static_cast<A &&>(a)))) + : T(X(), static_cast<A &&>(a)) {} + }; + + template<typename X, typename Y> struct U : T<X, Y> { + using T<X, Y>::T; + }; + + U<S, char> foo(char ch) { return U<S, char>(ch); } + + int main() { + U<S, int> a(42); + U<S, char> b('4'); + return 0; + } +} diff --git a/test/SemaCXX/cxx11-thread-local-print.cpp b/test/SemaCXX/cxx11-thread-local-print.cpp new file mode 100644 index 0000000..9d9a82b --- /dev/null +++ b/test/SemaCXX/cxx11-thread-local-print.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-linux-gnu -ast-print %s | FileCheck %s + +// CHECK: __thread int gnu_tl; +// CHECK: _Thread_local int c11_tl; +// CHECK: thread_local int cxx11_tl; +__thread int gnu_tl; +_Thread_local int c11_tl; +thread_local int cxx11_tl; + diff --git a/test/SemaCXX/cxx11-thread-local.cpp b/test/SemaCXX/cxx11-thread-local.cpp new file mode 100644 index 0000000..f1dddc1 --- /dev/null +++ b/test/SemaCXX/cxx11-thread-local.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-linux-gnu -verify %s + +struct S { + static thread_local int a; + static int b; // expected-note {{here}} + thread_local int c; // expected-error {{'thread_local' is only allowed on variable declarations}} + static thread_local int d; // expected-note {{here}} +}; + +thread_local int S::a; +thread_local int S::b; // expected-error {{thread-local declaration of 'b' follows non-thread-local declaration}} +thread_local int S::c; // expected-error {{non-static data member defined out-of-line}} +int S::d; // expected-error {{non-thread-local declaration of 'd' follows thread-local declaration}} + +thread_local int x[3]; +thread_local int y[3]; +thread_local int z[3]; // expected-note {{previous}} + +void f() { + thread_local int x; + static thread_local int y; + extern thread_local int z; // expected-error {{redefinition of 'z' with a different type}} +} diff --git a/test/SemaCXX/cxx11-user-defined-literals-unused.cpp b/test/SemaCXX/cxx11-user-defined-literals-unused.cpp new file mode 100644 index 0000000..cd93ffb --- /dev/null +++ b/test/SemaCXX/cxx11-user-defined-literals-unused.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wunused + +namespace { +double operator"" _x(long double value) { return double(value); } +int operator"" _ii(long double value) { return int(value); } // expected-warning {{not needed and will not be emitted}} +} + +namespace rdar13589856 { + template<class T> double value() { return 3.2_x; } + template<class T> int valuei() { return 3.2_ii; } + + double get_value() { return value<double>(); } +} diff --git a/test/SemaCXX/cxx1y-array-runtime-bound.cpp b/test/SemaCXX/cxx1y-array-runtime-bound.cpp new file mode 100644 index 0000000..1643adb --- /dev/null +++ b/test/SemaCXX/cxx1y-array-runtime-bound.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++1y %s -verify -triple=x86_64-linux-gnu -pedantic-errors + +// FIXME: many diagnostics here say 'variably modified type'. +// catch this case and say 'array of runtime bound' instead. + +namespace std { struct type_info; } + +struct S { + int arr[__SIZE_MAX__ / 32]; +}; +S s[32]; // expected-error {{array is too large}} + +int n; +int a[n]; // expected-error {{not allowed at file scope}} + +struct T { + int a[n]; // expected-error {{fields must have a constant size}} + static int b[n]; // expected-error {{not allowed at file scope}} +}; + +int g(int n, int a[n]); + +template<typename T> struct X {}; +template<int N, int[N]> struct Y {}; +template<int[n]> struct Z {}; // expected-error {{of variably modified type}} + +int f(int n) { + int arb[n]; // expected-note 3{{here}} + [arb] {} (); // expected-error {{cannot be captured}} + + // FIXME: an array of runtime bound can be captured by reference. + [&arb] { // expected-error {{cannot be captured}} + // Capturing the array implicitly captures the bound, if we need it + // in a range-based for loop. + for (auto &n : arb) { } // expected-error {{cannot be captured}} + } (); + + X<int[n]> x; // expected-error {{variably modified type}} + + int arb_neg[-1]; // expected-error {{negative size}} + int arb_of_array[n][2]; + int arr[3] = { 1, 2, 3, 4 }; // expected-error {{excess elements}} + char foo[4] = "fool"; // expected-error {{initializer-string for char array is too long}} + + static int not_auto1[n]; // expected-error {{can not have 'static'}} + extern int not_auto2[n]; // expected-error {{can not have 'extern'}} + // FIXME: say 'thread_local' not 'static'. + thread_local int not_auto1[n]; // expected-error {{can not have 'static'}} + + // FIXME: these should all be invalid. + auto &&ti1 = typeid(arb); + auto &&ti2 = typeid(int[n]); + auto &&so1 = sizeof(arb); + auto &&so2 = sizeof(int[n]); + auto *p = &arb; + decltype(arb) arb2; + int (*arbp)[n] = 0; + const int (&arbr)[n] = arbr; // expected-warning {{not yet bound}} + typedef int arbty[n]; + int array_of_arb[2][n]; + + struct Dyn { Dyn() {} Dyn(int) {} ~Dyn() {} }; + + // FIXME: these should be valid. + int arb_dynamic[n] = { 1, 2, 3, 4 }; // expected-error {{may not be initialized}} + Dyn dyn[n]; // expected-error {{non-POD}} + Dyn dyn_init[n] = { 1, 2, 3, 4 }; // expected-error {{non-POD}} +} diff --git a/test/SemaCXX/cxx1y-constexpr-not-const.cpp b/test/SemaCXX/cxx1y-constexpr-not-const.cpp new file mode 100644 index 0000000..3f100b8 --- /dev/null +++ b/test/SemaCXX/cxx1y-constexpr-not-const.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify +// RUN: %clang_cc1 -std=c++1y %s -verify -DCXX1Y + +struct X { + constexpr int f(); // @5 + int f(); // @6 +}; + +#ifdef CXX1Y +// FIXME: Detect this situation and provide a better recovery. + +// expected-error@6 {{class member cannot be redeclared}} +// expected-note@5 {{previous}} +// expected-error@6 {{non-constexpr declaration of 'f' follows constexpr declaration}} +// expected-note@5 {{previous}} +#else +// expected-warning@5 {{'constexpr' non-static member function will not be implicitly 'const' in C++1y; add 'const' to avoid a change in behavior}} +#endif diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp new file mode 100644 index 0000000..f0146f8 --- /dev/null +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -0,0 +1,338 @@ +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s + +auto f(); // expected-note {{previous}} +int f(); // expected-error {{differ only in their return type}} + +auto &g(); +auto g() -> auto &; + +auto h() -> auto *; +auto *h(); + +struct Conv1 { + operator auto(); // expected-note {{declared here}} +} conv1; +int conv1a = conv1; // expected-error {{function 'operator auto' with deduced return type cannot be used before it is defined}} +// expected-error@-1 {{no viable conversion}} +Conv1::operator auto() { return 123; } +int conv1b = conv1; +int conv1c = conv1.operator auto(); +int conv1d = conv1.operator int(); // expected-error {{no member named 'operator int'}} + +struct Conv2 { + operator auto() { return 0; } // expected-note 2{{previous}} + operator auto() { return 0.; } // expected-error {{cannot be redeclared}} expected-error {{redefinition of 'operator auto'}} +}; + +struct Conv3 { + operator auto() { int *p = nullptr; return p; } // expected-note {{candidate}} + operator auto*() { int *p = nullptr; return p; } // expected-note {{candidate}} +} conv3; +int *conv3a = conv3; // expected-error {{ambiguous}} +int *conv3b = conv3.operator auto(); +int *conv3c = conv3.operator auto*(); + +template<typename T> +struct Conv4 { + operator auto() { return T(); } +}; +Conv4<int> conv4int; +int conv4a = conv4int; +int conv4b = conv4int.operator auto(); + +auto a(); +auto a() { return 0; } +using T = decltype(a()); +using T = int; +auto a(); // expected-note {{previous}} +using T = decltype(a()); +auto *a(); // expected-error {{differ only in their return type}} + +auto b(bool k) { + if (k) + return "hello"; + return "goodbye"; +} + +auto *ptr_1() { + return 100; // expected-error {{cannot deduce return type 'auto *' from returned value of type 'int'}} +} + +const auto &ref_1() { + return 0; // expected-warning {{returning reference to local temporary}} +} + +auto init_list() { + return { 1, 2, 3 }; // expected-error {{cannot deduce return type from initializer list}} +} + +auto fwd_decl(); // expected-note 2{{here}} + +int n = fwd_decl(); // expected-error {{function 'fwd_decl' with deduced return type cannot be used before it is defined}} +int k = sizeof(fwd_decl()); // expected-error {{used before it is defined}} + +auto fac(int n) { + if (n <= 2) + return n; + return n * fac(n-1); // ok +} + +auto fac_2(int n) { // expected-note {{declared here}} + if (n > 2) + return n * fac_2(n-1); // expected-error {{cannot be used before it is defined}} + return n; +} + +auto void_ret() {} +using Void = void; +using Void = decltype(void_ret()); + +auto &void_ret_2() {} // expected-error {{cannot deduce return type 'auto &' for function with no return statements}} +const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 'void' + +const auto void_ret_4() { + if (false) + return void(); + if (false) + return; + return 0; // expected-error {{'auto' in return type deduced as 'int' here but deduced as 'void' in earlier return statement}} +} + +namespace Templates { + template<typename T> auto f1() { + return T() + 1; + } + template<typename T> auto &f2(T &&v) { return v; } + int a = f1<int>(); + const int &b = f2(0); + double d; + float &c = f2(0.0); // expected-error {{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'double'}} + + template<typename T> auto fwd_decl(); // expected-note {{declared here}} + int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}} + template<typename T> auto fwd_decl() { return 0; } + int f = fwd_decl<int>(); + template<typename T> auto fwd_decl(); + int g = fwd_decl<char>(); + + auto (*p)() = f1; // expected-error {{incompatible initializer}} + auto (*q)() = f1<int>; // ok + + typedef decltype(f2(1.2)) dbl; // expected-note {{previous}} + typedef float dbl; // expected-error {{typedef redefinition with different types ('float' vs 'decltype(f2(1.2))' (aka 'double &'))}} + + extern template auto fwd_decl<double>(); + int k1 = fwd_decl<double>(); + extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}} + int k2 = fwd_decl<char>(); + + template<typename T> auto instantiate() { T::error; } // expected-error {{has no members}} + extern template auto instantiate<int>(); // ok + int k = instantiate<int>(); // expected-note {{in instantiation of}} + template<> auto instantiate<char>() {} // ok + template<> void instantiate<double>() {} // expected-error {{no function template matches}} + + template<typename T> auto arg_single() { return 0; } + template<typename T> auto arg_multi() { return 0l; } + template<typename T> auto arg_multi(int) { return "bad"; } + template<typename T> struct Outer { + static auto arg_single() { return 0.f; } + static auto arg_multi() { return 0.; } + static auto arg_multi(int) { return "bad"; } + }; + template<typename T> T &take_fn(T (*p)()); + + int &check1 = take_fn(arg_single); // expected-error {{no matching}} expected-note@-2 {{couldn't infer}} + int &check2 = take_fn(arg_single<int>); + int &check3 = take_fn<int>(arg_single); // expected-error {{no matching}} expected-note@-4{{no overload of 'arg_single'}} + int &check4 = take_fn<int>(arg_single<int>); + long &check5 = take_fn(arg_multi); // expected-error {{no matching}} expected-note@-6 {{couldn't infer}} + long &check6 = take_fn(arg_multi<int>); + long &check7 = take_fn<long>(arg_multi); // expected-error {{no matching}} expected-note@-8{{no overload of 'arg_multi'}} + long &check8 = take_fn<long>(arg_multi<int>); + + float &mem_check1 = take_fn(Outer<int>::arg_single); + float &mem_check2 = take_fn<float>(Outer<char>::arg_single); + double &mem_check3 = take_fn(Outer<long>::arg_multi); + double &mem_check4 = take_fn<double>(Outer<double>::arg_multi); + + namespace Deduce1 { + template<typename T> auto f() { return 0; } // expected-note {{candidate}} + template<typename T> void g(T(*)()); // expected-note 2{{candidate}} + void h() { + auto p = f<int>; + auto (*q)() = f<int>; + int (*r)() = f; // expected-error {{does not match}} + g(f<int>); + g<int>(f); // expected-error {{no matching function}} + g(f); // expected-error {{no matching function}} + } + } + + namespace Deduce2 { + template<typename T> auto f(int) { return 0; } // expected-note {{candidate}} + template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}} + void h() { + auto p = f<int>; + auto (*q)(int) = f<int>; + int (*r)(int) = f; // expected-error {{does not match}} + g(f<int>); + g<int>(f); // expected-error {{no matching function}} + g(f); // expected-error {{no matching function}} + } + } + + namespace Deduce3 { + template<typename T> auto f(T) { return 0; } + template<typename T> void g(T(*)(int)); // expected-note {{couldn't infer}} + void h() { + auto p = f<int>; + auto (*q)(int) = f<int>; + int (*r)(int) = f; // ok + g(f<int>); + g<int>(f); // ok + g(f); // expected-error {{no matching function}} + } + } + + namespace DeduceInDeducedReturnType { + template<typename T, typename U> auto f() -> auto (T::*)(U) { + int (T::*result)(U) = nullptr; + return result; + } + struct S {}; + int (S::*(*p)())(double) = f; + int (S::*(*q)())(double) = f<S, double>; + } +} + +auto fwd_decl_using(); +namespace N { using ::fwd_decl_using; } +auto fwd_decl_using() { return 0; } +namespace N { int k = N::fwd_decl_using(); } + +namespace OverloadResolutionNonTemplate { + auto f(); + auto f(int); // expected-note {{here}} + + int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}} + char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}} + + int a = g(f); // expected-error {{no matching function}} + + auto f() { return 0; } + + // FIXME: It's not completely clear whether this should be ill-formed. + int &b = g(f); // expected-error {{used before it is defined}} + + auto f(int) { return 0.0; } + + int &c = g(f); // ok +} + +namespace OverloadResolutionTemplate { + auto f(); + template<typename T> auto f(T); + + int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}} expected-note {{candidate}} + char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}} expected-note {{candidate}} + + int a = g(f); // expected-error {{no matching function}} + + auto f() { return 0; } + + int &b = g(f); // ok (presumably), due to deduction failure forming type of 'f<int>' + + template<typename T> auto f(T) { return 0; } + + int &c = g(f); // expected-error {{ambiguous}} +} + +namespace DefaultedMethods { + struct A { + auto operator=(const A&) = default; // expected-error {{must return 'DefaultedMethods::A &'}} + A &operator=(A&&); // expected-note {{previous}} + }; + auto A::operator=(A&&) = default; // expected-error {{differs from the declaration in the return type}} +} + +namespace Constexpr { + constexpr auto f1(int n) { return n; } + struct NonLiteral { ~NonLiteral(); } nl; // expected-note {{user-provided destructor}} + constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}} +} + +// It's not really clear whether these are valid, but this matches g++. +using size_t = decltype(sizeof(0)); +auto operator new(size_t n, const char*); // expected-error {{must return type 'void *'}} +auto operator delete(void *, const char*); // expected-error {{must return type 'void'}} + +namespace Virtual { + struct S { + virtual auto f() { return 0; } // expected-error {{function with deduced return type cannot be virtual}} expected-note {{here}} + }; + // Allow 'auto' anyway for error recovery. + struct T : S { + int f(); + }; + struct U : S { + auto f(); // expected-error {{different return}} + }; + + // And here's why... + struct V { virtual auto f(); }; // expected-error {{cannot be virtual}} + struct W : V { virtual auto f(); }; // expected-error {{cannot be virtual}} + auto V::f() { return 0; } // in tu1.cpp + auto W::f() { return 0.0; } // in tu2.cpp + W w; + int k1 = w.f(); + int k2 = ((V&)w).f(); +} + +namespace std_examples { + +namespace NoReturn { + auto f() {} + void (*p)() = &f; + + auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} +} + +namespace UseBeforeComplete { + auto n = n; // expected-error {{variable 'n' declared with 'auto' type cannot appear in its own initializer}} + auto f(); // expected-note {{declared here}} + void g() { &f; } // expected-error {{function 'f' with deduced return type cannot be used before it is defined}} + auto sum(int i) { + if (i == 1) + return i; + else + return sum(i - 1) + i; + } +} + +namespace Redecl { + auto f(); + auto f() { return 42; } + auto f(); // expected-note 2{{previous}} + int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}} + decltype(auto) f(); // expected-error {{cannot be overloaded}} + + template<typename T> auto g(T t) { return t; } // expected-note {{candidate}} + template auto g(int); + template char g(char); // expected-error {{does not refer to a function}} + template<> auto g(double); + + template<typename T> T g(T t) { return t; } // expected-note {{candidate}} + template char g(char); + template auto g(float); + + void h() { return g(42); } // expected-error {{ambiguous}} +} + +namespace ExplicitInstantiationDecl { + template<typename T> auto f(T t) { return t; } + extern template auto f(int); + int (*p)(int) = f; +} + +} diff --git a/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/test/SemaCXX/cxx1y-initializer-aggregates.cpp new file mode 100644 index 0000000..9b54240 --- /dev/null +++ b/test/SemaCXX/cxx1y-initializer-aggregates.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -std=c++1y %s -verify + +namespace in_class_init { + union U { char c; double d = 4.0; }; + constexpr U u1 = U(); + constexpr U u2 {}; + constexpr U u3 { 'x' }; + static_assert(u1.d == 4.0, ""); + static_assert(u2.d == 4.0, ""); + static_assert(u3.c == 'x', ""); + + struct A { + int n = 5; + int m = n * 3; + union { + char c; + double d = 4.0; + }; + }; + constexpr A a1 {}; + constexpr A a2 { 8 }; + constexpr A a3 { 1, 2, { 3 } }; + constexpr A a4 { 1, 2, { .d = 3.0 } }; + static_assert(a1.d == 4.0, ""); + static_assert(a2.m == 24, ""); + static_assert(a2.d == 4.0, ""); + static_assert(a3.c == 3, ""); + static_assert(a3.d == 4.0, ""); // expected-error {{constant expression}} expected-note {{active member 'c'}} + static_assert(a4.d == 3.0, ""); + + struct B { + int n; + constexpr int f() { return n * 5; } + int m = f(); + }; + B b1 {}; + constexpr B b2 { 2 }; + B b3 { 1, 2 }; + static_assert(b2.m == 10, ""); + + struct C { + int k; + union { + int l = k; // expected-error {{invalid use of non-static}} + }; + }; +} + +namespace nested_aggregate_init { + struct A { + int n = 5; + int b = n * 3; + }; + struct B { + constexpr B(int k) : d(1.23), k(k) {} + // Within this aggregate, both this object's 'this' and the temporary's + // 'this' are used. + constexpr int f() const { return A{k}.b; } + double d; + int k; + }; + static_assert(B(6).f() == 18, ""); +} diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp index 18fd152..208ea4c 100644 --- a/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -1,3 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat-pedantic -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Werror %s // RUN: %clang_cc1 -fsyntax-only -std=c++98 -Werror %s @@ -38,3 +40,12 @@ long long ll1 = // expected-warning {{'long long' is incompatible with C++98}} unsigned long long ull1 = // expected-warning {{'long long' is incompatible with C++98}} 42ULL; // expected-warning {{'long long' is incompatible with C++98}} +int k = 0b1001; +#ifdef CXX1Y +// expected-warning@-2 {{binary integer literals are incompatible with C++ standards before C++1y}} +#endif + +void f(int n) { int a[n]; } +#ifdef CXX1Y +// expected-warning@-2 {{arrays of runtime bound are incompatible with C++ standards before C++1y}} +#endif diff --git a/test/SemaCXX/enum-unscoped-nonexistent.cpp b/test/SemaCXX/enum-unscoped-nonexistent.cpp index d49800c..e9da38f 100644 --- a/test/SemaCXX/enum-unscoped-nonexistent.cpp +++ b/test/SemaCXX/enum-unscoped-nonexistent.cpp @@ -5,8 +5,8 @@ struct Base { }; template<typename T> struct S : Base { enum E : int; - constexpr int f(); - constexpr int g(); // expected-note {{declared here}} + constexpr int f() const; + constexpr int g() const; // expected-note {{declared here}} void h(); }; template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}} @@ -16,13 +16,13 @@ template<typename T> enum S<T>::E : int { b = 8 }; // The unqualified-id here names a member of the non-dependent base class Base // and not the injected enumerator name 'a' from the specialization. -template<typename T> constexpr int S<T>::f() { return a; } +template<typename T> constexpr int S<T>::f() const { return a; } static_assert(S<char>().f() == 1, ""); static_assert(S<int>().f() == 1, ""); // The unqualified-id here names a member of the current instantiation, which // bizarrely might not exist in some instantiations. -template<typename T> constexpr int S<T>::g() { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}} +template<typename T> constexpr int S<T>::g() const { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}} static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} expected-note {{undefined}} static_assert(S<short>().g() == 2, ""); static_assert(S<long>().g() == 8, ""); diff --git a/test/SemaCXX/for-range-unused.cpp b/test/SemaCXX/for-range-unused.cpp index ce6b379..ec11015 100644 --- a/test/SemaCXX/for-range-unused.cpp +++ b/test/SemaCXX/for-range-unused.cpp @@ -7,7 +7,7 @@ template <typename T> void doIt() { int a; // expected-warning {{unused variable 'a'}} - for (auto& e : elements) + for (auto& e : elements) // expected-warning {{unused variable 'e'}} ; } @@ -17,5 +17,5 @@ template <typename T> int main(int, char**) { Vector<int> vector; - vector.doIt(); + vector.doIt(); // expected-note {{here}} } diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index 5631577..c80323c 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -60,7 +60,7 @@ int* y = reinterpret_cast<const char&>(x); // expected-error {{cannot initialize // This isn't an integral constant expression, but make sure it folds anyway. struct PR8836 { char _; long long a; }; // expected-warning {{long long}} -int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} +int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} const int nonconst = 1.0; // expected-note {{declared here}} int arr[nonconst]; // expected-warning {{folded to constant array as an extension}} expected-note {{initializer of 'nonconst' is not a constant expression}} diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp index 0ba9508..504df0d 100644 --- a/test/SemaCXX/linkage-spec.cpp +++ b/test/SemaCXX/linkage-spec.cpp @@ -106,3 +106,11 @@ namespace PR9162 { return sizeof(ArtsSink); } } + +namespace pr14958 { + namespace js { extern int ObjectClass; } + extern "C" { + namespace js {} + } + int js::ObjectClass; +} diff --git a/test/SemaCXX/linkage.cpp b/test/SemaCXX/linkage.cpp index 6b73d59..13d295a 100644 --- a/test/SemaCXX/linkage.cpp +++ b/test/SemaCXX/linkage.cpp @@ -94,3 +94,12 @@ extern "C" { // CHECK: define linkonce_odr i8* @_ZN5test21A1BILj0EE3fooEv( // CHECK: define linkonce_odr i8* @_ZN5test11A3fooILj0EEEPvv( + +namespace test5 { + struct foo { + }; + extern "C" { + const foo bar[] = { + }; + } +} diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp index ddf4064..3cfa981 100644 --- a/test/SemaCXX/linkage2.cpp +++ b/test/SemaCXX/linkage2.cpp @@ -152,3 +152,15 @@ namespace test15 { const int a = 5; // expected-note {{previous definition is here}} static const int a; // expected-error {{redefinition of 'a'}} } + +namespace test16 { + extern "C" { + class Foo { + int x; + friend int bar(Foo *y); + }; + int bar(Foo *y) { + return y->x; + } + } +} diff --git a/test/SemaCXX/pascal-strings.cpp b/test/SemaCXX/pascal-strings.cpp index 89194b5..f4c692d 100644 --- a/test/SemaCXX/pascal-strings.cpp +++ b/test/SemaCXX/pascal-strings.cpp @@ -4,3 +4,5 @@ const wchar_t *pascalString = L"\pThis is a Pascal string"; unsigned char a[3] = "\pa"; unsigned char b[3] = "\pab"; unsigned char c[3] = "\pabc"; // expected-error {{initializer-string for char array is too long}} +unsigned char d[3] = ("\pab"); +unsigned char e[3] = ("\pabc"); // expected-error {{initializer-string for char array is too long}} diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp index 462b4fa..bd601db 100644 --- a/test/SemaCXX/trailing-return-0x.cpp +++ b/test/SemaCXX/trailing-return-0x.cpp @@ -85,3 +85,12 @@ namespace PR12053 { f2(0); // expected-error{{no matching function for call to 'f2'}} } } + +namespace DR1608 { + struct S { + void operator+(); + int operator[](int); + auto f() -> decltype(+*this); // expected-note {{here}} + auto f() -> decltype((*this)[0]); // expected-error {{cannot be overloaded}} + }; +} diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp index 839fdaf..1b76a86 100644 --- a/test/SemaCXX/undefined-internal.cpp +++ b/test/SemaCXX/undefined-internal.cpp @@ -323,3 +323,10 @@ namespace test13 { } } +namespace test14 { + extern "C" const int foo; + + int f() { + return foo; + } +} diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 2aa5662..665cfe7 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -511,3 +511,15 @@ namespace operators { int x = x = 5; } + +namespace lambdas { + struct A { + template<typename T> A(T) {} + int x; + }; + A a0([] { return a0.x; }); // ok + void f() { + A a1([=] { return a1.x; }); // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}} + A a2([&] { return a2.x; }); // ok + } +} diff --git a/test/SemaCXX/warn-c++11-extensions.cpp b/test/SemaCXX/warn-c++11-extensions.cpp index 8f35171..bf8612a 100644 --- a/test/SemaCXX/warn-c++11-extensions.cpp +++ b/test/SemaCXX/warn-c++11-extensions.cpp @@ -5,3 +5,5 @@ long long ll1 = // expected-warning {{'long long' is a C++11 extension}} unsigned long long ull1 = // expected-warning {{'long long' is a C++11 extension}} 42ULL; // expected-warning {{'long long' is a C++11 extension}} +enum struct E1 { A, B }; // expected-warning {{scoped enumerations are a C++11 extension}} +enum class E2 { C, D }; // expected-warning {{scoped enumerations are a C++11 extension}} diff --git a/test/SemaCXX/warn-overloaded-virtual.cpp b/test/SemaCXX/warn-overloaded-virtual.cpp index 9b0f5aa..629d59d 100644 --- a/test/SemaCXX/warn-overloaded-virtual.cpp +++ b/test/SemaCXX/warn-overloaded-virtual.cpp @@ -120,3 +120,21 @@ struct MostDerived: Derived3, Derived2 { void func(); }; } + +namespace { + class A { + virtual int foo(bool) const; + // expected-note@-1{{type mismatch at 1st parameter ('bool' vs 'int')}} + virtual int foo(int, int) const; + // expected-note@-1{{different number of parameters (2 vs 1)}} + virtual int foo(int*) const; + // expected-note@-1{{type mismatch at 1st parameter ('int *' vs 'int')}} + virtual int foo(int) volatile; + // expected-note@-1{{different qualifiers (volatile vs const)}} + }; + + class B : public A { + virtual int foo(int) const; + // expected-warning@-1{{hides overloaded virtual functions}} + }; +} diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 3f41124..bc4b40e 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -1475,8 +1475,8 @@ namespace substitution_test { public: Mutex mu; - void lockData() __attribute__((exclusive_lock_function(mu))) { } - void unlockData() __attribute__((unlock_function(mu))) { } + void lockData() __attribute__((exclusive_lock_function(mu))); + void unlockData() __attribute__((unlock_function(mu))); void doSomething() __attribute__((exclusive_locks_required(mu))) { } }; @@ -1484,8 +1484,8 @@ namespace substitution_test { class DataLocker { public: - void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { } - void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { } + void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))); + void unlockData(MyData *d) __attribute__((unlock_function(d->mu))); }; @@ -2858,7 +2858,7 @@ void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) { } void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) { - mu1_.Lock(); + mu1_.ReaderLock(); } void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) { @@ -3640,8 +3640,8 @@ class Foo { LOCKS_EXCLUDED(mu2_); void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_) EXCLUSIVE_LOCK_FUNCTION(mu2_); - void readerlock() EXCLUSIVE_LOCK_FUNCTION(mu1_) - EXCLUSIVE_LOCK_FUNCTION(mu2_); + void readerlock() SHARED_LOCK_FUNCTION(mu1_) + SHARED_LOCK_FUNCTION(mu2_); void unlock() UNLOCK_FUNCTION(mu1_) UNLOCK_FUNCTION(mu2_); bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_) @@ -3663,9 +3663,9 @@ void Foo::foo2() { } void Foo::foo3() { } -void Foo::lock() { } -void Foo::readerlock() { } -void Foo::unlock() { } +void Foo::lock() { mu1_.Lock(); mu2_.Lock(); } +void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); } +void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); } bool Foo::trylock() { return true; } bool Foo::readertrylock() { return true; } @@ -3915,3 +3915,73 @@ void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2()); } // end namespace UnevaluatedContextTest + +namespace LockUnlockFunctionTest { + +// Check built-in lock functions +class LOCKABLE MyLockable { +public: + void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); } + void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); } + void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); } + +private: + Mutex mu_; +}; + + +class Foo { +public: + // Correct lock/unlock functions + void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) { + mu_.Lock(); + } + + void readerLock() SHARED_LOCK_FUNCTION(mu_) { + mu_.ReaderLock(); + } + + void unlock() UNLOCK_FUNCTION(mu_) { + mu_.Unlock(); + } + + // Check failure to lock. + void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} + mu2_.Lock(); + mu2_.Unlock(); + } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} + + void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} + mu2_.Lock(); + mu2_.Unlock(); + } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} + + void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} + mu2_.Lock(); + mu2_.Unlock(); + } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + + // Check locking the wrong thing. + void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} + mu2_.Lock(); // expected-note {{mutex acquired here}} + } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} \ + // expected-warning {{mutex 'mu2_' is still locked at the end of function}} + + + void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} + mu2_.ReaderLock(); // expected-note {{mutex acquired here}} + } // expected-warning {{expecting mutex 'mu_' to be locked at the end of function}} \ + // expected-warning {{mutex 'mu2_' is still locked at the end of function}} + + + void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}} + mu2_.Unlock(); // expected-warning {{unlocking 'mu2_' that was not locked}} + } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + +private: + Mutex mu_; + Mutex mu2_; +}; + +} // end namespace LockUnlockFunctionTest + diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp index e12668b..9fb6011 100644 --- a/test/SemaCXX/warn-unused-filescoped.cpp +++ b/test/SemaCXX/warn-unused-filescoped.cpp @@ -133,6 +133,27 @@ namespace test6 { }; } +namespace test7 +{ + template<typename T> + static inline void foo(T) { } + + // This should not emit an unused-function warning since it inherits + // the static storage type from the base template. + template<> + inline void foo(int) { } + + // Partial specialization + template<typename T, typename U> + static inline void bar(T, U) { } + + template<typename U> + inline void bar(int, U) { } + + template<> + inline void bar(int, int) { } +}; + namespace pr14776 { namespace { struct X {}; diff --git a/test/SemaCXX/warn-unused-variables-error.cpp b/test/SemaCXX/warn-unused-variables-error.cpp new file mode 100644 index 0000000..6386c4b --- /dev/null +++ b/test/SemaCXX/warn-unused-variables-error.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s + +namespace PR6948 { + template<typename T> class X; // expected-note{{template is declared here}} + + void f() { + X<char> str (read_from_file()); // expected-error{{use of undeclared identifier 'read_from_file'}} \ + expected-error{{implicit instantiation of undefined template 'PR6948::X<char>'}} + } +} diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 4e8d51d..00597f9 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -41,15 +41,6 @@ void test_dependent_init(T *p) { (void)i; } -namespace PR6948 { - template<typename T> class X; // expected-note{{template is declared here}} - - void f() { - X<char> str (read_from_file()); // expected-error{{use of undeclared identifier 'read_from_file'}} \ - expected-error{{implicit instantiation of undefined template 'PR6948::X<char>'}} - } -} - void unused_local_static() { static int x = 0; static int y = 0; // expected-warning{{unused variable 'y'}} @@ -135,3 +126,5 @@ namespace ctor_with_cleanups { S2 s((S1())); } } + +#include "Inputs/warn-unused-variables.h" |