diff options
author | dim <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
commit | 50b73317314e889cf39c7b1d6cbf419fa7502f22 (patch) | |
tree | be1815eb79b42ff482a8562b13c2dcbf0c5dcbee /test/CXX/expr | |
parent | dc04cb328508e61aad809d9b53b12f9799a00e7d (diff) | |
download | FreeBSD-src-50b73317314e889cf39c7b1d6cbf419fa7502f22.zip FreeBSD-src-50b73317314e889cf39c7b1d6cbf419fa7502f22.tar.gz |
Vendor import of clang trunk r154661:
http://llvm.org/svn/llvm-project/cfe/trunk@r154661
Diffstat (limited to 'test/CXX/expr')
37 files changed, 2009 insertions, 24 deletions
diff --git a/test/CXX/expr/expr.ass/p9-cxx11.cpp b/test/CXX/expr/expr.ass/p9-cxx11.cpp new file mode 100644 index 0000000..206c82c --- /dev/null +++ b/test/CXX/expr/expr.ass/p9-cxx11.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +template<typename T> struct complex { + complex(T = T(), T = T()); + void operator+=(complex); + T a, b; +}; + +void std_example() { + complex<double> z; + z = { 1, 2 }; + z += { 1, 2 }; + + int a, b; + a = b = { 1 }; + a = { 1 } = b; // expected-error {{initializer list cannot be used on the left hand side of operator '='}} + a = a + { 4 }; // expected-error {{initializer list cannot be used on the right hand side of operator '+'}} + a = { 3 } * { 4 }; // expected-error {{initializer list cannot be used on the left hand side of operator '*'}} \ + expected-error {{initializer list cannot be used on the right hand side of operator '*'}} +} + +struct S { + constexpr S(int a, int b) : a(a), b(b) {} + int a, b; +}; +struct T { + constexpr int operator=(S s) { return s.a; } + constexpr int operator+=(S s) { return s.b; } +}; +static_assert((T() = {4, 9}) == 4, ""); +static_assert((T() += {4, 9}) == 9, ""); + +int k1 = T() = { 1, 2 } = { 3, 4 }; // expected-error {{initializer list cannot be used on the left hand side of operator '='}} +int k2 = T() = { 1, 2 } + 1; // expected-error {{initializer list cannot be used on the left hand side of operator '+'}} diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index 2c6a46b..054669e 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -1,7 +1,575 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -pedantic -verify -fcxx-exceptions %s -fconstexpr-depth 128 -triple i686-pc-linux-gnu + +// A conditional-expression is a core constant expression unless it involves one +// of the following as a potentially evaluated subexpression [...]: + +// - this (5.1.1 [expr.prim.general]) [Note: when evaluating a constant +// expression, function invocation substitution (7.1.5 [dcl.constexpr]) +// replaces each occurrence of this in a constexpr member function with a +// pointer to the class object. -end note]; +struct This { + int this1 : this1; // expected-error {{undeclared}} + int this2 : this->this1; // expected-error {{invalid}} + void this3() { + int n1[this->this1]; // expected-warning {{variable length array}} + int n2[this1]; // expected-warning {{variable length array}} + (void)n1, (void)n2; + } +}; + +// - an invocation of a function other than a constexpr constructor for a +// literal class or a constexpr function [ Note: Overload resolution (13.3) +// is applied as usual - end note ]; +struct NonConstexpr1 { + static int f() { return 1; } // expected-note {{here}} + int n : f(); // expected-error {{constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +}; +struct NonConstexpr2 { + constexpr NonConstexpr2(); // expected-note {{here}} + int n; +}; +struct NonConstexpr3 { + NonConstexpr3(); + int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}} +}; +struct NonConstexpr4 { + NonConstexpr4(); // expected-note {{declared here}} + int n; +}; +struct NonConstexpr5 { + int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}} +}; + +// - an invocation of an undefined constexpr function or an undefined +// constexpr constructor; +struct UndefinedConstexpr { + constexpr UndefinedConstexpr(); + static constexpr int undefinedConstexpr1(); // expected-note {{here}} + int undefinedConstexpr2 : undefinedConstexpr1(); // expected-error {{constant expression}} expected-note {{undefined function 'undefinedConstexpr1' cannot be used in a constant expression}} +}; + +// - an invocation of a constexpr function with arguments that, when substituted +// by function invocation substitution (7.1.5), do not produce a core constant +// expression; +namespace NonConstExprReturn { + static constexpr const int &id_ref(const int &n) { + return n; + } + struct NonConstExprFunction { + int n : id_ref(16); // ok + }; + constexpr const int *address_of(const int &a) { + return &a; + } + constexpr const int *return_param(int n) { // expected-note {{declared here}} + return address_of(n); + } + struct S { + int n : *return_param(0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}} + }; +} + +// - an invocation of a constexpr constructor with arguments that, when +// substituted by function invocation substitution (7.1.5), do not produce all +// constant expressions for the constructor calls and full-expressions in the +// mem-initializers (including conversions); +namespace NonConstExprCtor { + struct T { + constexpr T(const int &r) : + r(r) { + } + const int &r; + }; + constexpr int n = 0; + constexpr T t1(n); // ok + constexpr T t2(0); // expected-error {{must be initialized by a constant expression}} expected-note {{temporary created here}} expected-note {{reference to temporary is not a constant expression}} + + struct S { + int n : T(4).r; // ok + }; +} + +// - an invocation of a constexpr function or a constexpr constructor that would +// exceed the implementation-defined recursion limits (see Annex B); +namespace RecursionLimits { + constexpr int RecurseForever(int n) { + return n + RecurseForever(n+1); // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'RecurseForever(}} expected-note {{skipping 118 calls}} + } + struct AlsoRecurseForever { + constexpr AlsoRecurseForever(int n) : + n(AlsoRecurseForever(n+1).n) // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'AlsoRecurseForever(}} expected-note {{skipping 118 calls}} + {} + int n; + }; + struct S { + int k : RecurseForever(0); // expected-error {{constant expression}} expected-note {{in call to}} + int l : AlsoRecurseForever(0).n; // expected-error {{constant expression}} expected-note {{in call to}} + }; +} + +// DR1458: taking the address of an object of incomplete class type +namespace IncompleteClassTypeAddr { + struct S; + extern S s; + constexpr S *p = &s; // ok + static_assert(p, ""); + + extern S sArr[]; + constexpr S (*p2)[] = &sArr; // ok + + struct S { + constexpr S *operator&() { return nullptr; } + }; + constexpr S *q = &s; // ok + static_assert(!q, ""); +} + +// - an operation that would have undefined behavior [Note: including, for +// example, signed integer overflow (Clause 5 [expr]), certain pointer +// arithmetic (5.7 [expr.add]), division by zero (5.6 [expr.mul]), or certain +// shift operations (5.8 [expr.shift]) -end note]; +namespace UndefinedBehavior { + void f(int n) { + switch (n) { + case (int)4.4e9: // expected-error {{constant expression}} expected-note {{value 4.4E+9 is outside the range of representable values of type 'int'}} + case (int)0x80000000u: // ok + case (int)10000000000ll: // expected-note {{here}} + case (unsigned int)10000000000ll: // expected-error {{duplicate case value}} + case (int)(unsigned)(long long)4.4e9: // ok + case (int)(float)1e300: // expected-error {{constant expression}} expected-note {{value 1.0E+300 is outside the range of representable values of type 'float'}} + case (int)((float)1e37 / 1e30): // ok + case (int)(__fp16)65536: // expected-error {{constant expression}} expected-note {{value 65536 is outside the range of representable values of type 'half'}} + break; + } + } + + constexpr int int_min = ~0x7fffffff; + constexpr int minus_int_min = -int_min; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} + constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} + constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int int_min_mod_minus_1 = int_min % -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + + constexpr int shl_m1 = 0 << -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} + constexpr int shl_0 = 0 << 0; // ok + constexpr int shl_31 = 0 << 31; // ok + constexpr int shl_32 = 0 << 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type 'int' (32}} expected-warning {{>= width of type}} + constexpr int shl_unsigned_negative = unsigned(-3) << 1; // ok + constexpr int shl_unsigned_into_sign = 1u << 31; // ok + constexpr int shl_unsigned_overflow = 1024u << 31; // ok + constexpr int shl_signed_negative = (-3) << 1; // expected-error {{constant expression}} expected-note {{left shift of negative value -3}} + constexpr int shl_signed_ok = 1 << 30; // ok + constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457) + constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457) + constexpr int shl_signed_off_end = 2 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x100000000) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_off_end_2 = 0x7fffffff << 2; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x1FFFFFFFC) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_overflow = 1024 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{requires 43 bits to represent}} + constexpr int shl_signed_ok2 = 1024 << 20; // ok + + constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} + constexpr int shr_0 = 0 >> 0; // ok + constexpr int shr_31 = 0 >> 31; // ok + constexpr int shr_32 = 0 >> 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type}} expected-warning {{>= width of type}} + + struct S { + int m; + }; + constexpr S s = { 5 }; + constexpr const int *p = &s.m + 1; + constexpr const int &f(const int *q) { + return q[0]; + } + constexpr int n = (f(p), 0); // ok + struct T { + int n : f(p); // expected-error {{not an integral constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} + }; + + namespace Ptr { + struct A {}; + struct B : A { int n; }; + B a[3][3]; + constexpr B *p = a[0] + 4; // expected-error {{constant expression}} expected-note {{element 4 of array of 3 elements}} + B b = {}; + constexpr A *pa = &b + 1; // expected-error {{constant expression}} expected-note {{base class of pointer past the end}} + constexpr B *pb = (B*)((A*)&b + 1); // expected-error {{constant expression}} expected-note {{derived class of pointer past the end}} + constexpr const int *pn = &(&b + 1)->n; // expected-error {{constant expression}} expected-note {{field of pointer past the end}} + constexpr B *parr = &a[3][0]; // expected-error {{constant expression}} expected-note {{array element of pointer past the end}} + + constexpr A *na = nullptr; + constexpr B *nb = nullptr; + constexpr A &ra = *nb; // expected-error {{constant expression}} expected-note {{cannot access base class of null pointer}} + constexpr B &rb = (B&)*na; // expected-error {{constant expression}} expected-note {{cannot access derived class of null pointer}} + static_assert((A*)nb == 0, ""); + static_assert((B*)na == 0, ""); + constexpr const int &nf = nb->n; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}} + constexpr const int &np = (*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot access array element of null pointer}} + + struct C { + constexpr int f() { return 0; } + } constexpr c = C(); + constexpr int k1 = c.f(); // ok + constexpr int k2 = ((C*)nullptr)->f(); // expected-error {{constant expression}} expected-note {{cannot call member function on null pointer}} + constexpr int k3 = (&c)[1].f(); // expected-error {{constant expression}} expected-note {{cannot call member function on pointer past the end of object}} + C c2; + constexpr int k4 = c2.f(); // ok! + + constexpr int diff1 = &a[2] - &a[0]; + constexpr int diff2 = &a[1][3] - &a[1][0]; + constexpr int diff3 = &a[2][0] - &a[1][0]; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + static_assert(&a[2][0] == &a[1][3], ""); + constexpr int diff4 = (&b + 1) - &b; + constexpr int diff5 = &a[1][2].n - &a[1][0].n; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + constexpr int diff6 = &a[1][2].n - &a[1][2].n; + constexpr int diff7 = (A*)&a[0][1] - (A*)&a[0][0]; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + } + + namespace Overflow { + // Signed int overflow. + constexpr int n1 = 2 * 3 * 3 * 7 * 11 * 31 * 151 * 331; // ok + constexpr int n2 = 65536 * 32768; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n3 = n1 + 1; // ok + constexpr int n4 = n3 + 1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n5 = -65536 * 32768; // ok + constexpr int n6 = 3 * -715827883; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n7 = -n3 + -1; // ok + constexpr int n8 = -1 + n7; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n9 = n3 - 0; // ok + constexpr int n10 = n3 - -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n11 = -1 - n3; // ok + constexpr int n12 = -2 - n3; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }} + constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }} + constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }} + constexpr signed char c1 = 100 * 2; // ok + constexpr signed char c2 = '\x64' * '\2'; // also ok + constexpr long long ll1 = 0x7fffffffffffffff; // ok + constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }} + constexpr long long ll3 = -ll1 - 1; // ok + constexpr long long ll4 = ll3 - 1; // expected-error {{constant}} expected-note {{ -9223372036854775809 }} + constexpr long long ll5 = ll3 * ll3; // expected-error {{constant}} expected-note {{ 85070591730234615865843651857942052864 }} + + // Yikes. + char melchizedek[2200000000]; + typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t; + constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok + constexpr ptrdiff_t d2 = &melchizedek[0x80000000u] - &melchizedek[0]; // expected-error {{constant expression}} expected-note {{ 2147483648 }} + constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok + constexpr ptrdiff_t d4 = &melchizedek[0] - &melchizedek[0x80000001u]; // expected-error {{constant expression}} expected-note {{ -2147483649 }} + + // Unsigned int overflow. + static_assert(65536u * 65536u == 0u, ""); // ok + static_assert(4294967295u + 1u == 0u, ""); // ok + static_assert(0u - 1u == 4294967295u, ""); // ok + static_assert(~0u * ~0u == 1u, ""); // ok + + // Floating-point overflow and NaN. + constexpr float f1 = 1e38f * 3.4028f; // ok + constexpr float f2 = 1e38f * 3.4029f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f3 = 1e38f / -.2939f; // ok + constexpr float f4 = 1e38f / -.2938f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f5 = 2e38f + 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f6 = -2e38f - 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f7 = 0.f / 0.f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces a NaN}} + } +} + +// - a lambda-expression (5.1.2); +struct Lambda { + // FIXME: clang crashes when trying to parse this! Revisit this check once + // lambdas are fully implemented. + //int n : []{ return 1; }(); +}; + +// - an lvalue-to-rvalue conversion (4.1) unless it is applied to +namespace LValueToRValue { + // - a non-volatile glvalue of integral or enumeration type that refers to a + // non-volatile const object with a preceding initialization, initialized + // with a constant expression [Note: a string literal (2.14.5 [lex.string]) + // corresponds to an array of such objects. -end note], or + volatile const int vi = 1; // expected-note 2{{here}} + const int ci = 1; + volatile const int &vrci = ci; + static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + + // - a non-volatile glvalue of literal type that refers to a non-volatile + // object defined with constexpr, or that refers to a sub-object of such an + // object, or + struct V { + constexpr V() : v(1) {} + volatile int v; // expected-note {{not literal because}} + }; + constexpr V v; // expected-error {{non-literal type}} + struct S { + constexpr S(int=0) : i(1), v(const_cast<volatile int&>(vi)) {} + constexpr S(const S &s) : i(2), v(const_cast<volatile int&>(vi)) {} + int i; + volatile int &v; + }; + constexpr S s; // ok + constexpr volatile S vs; // expected-note {{here}} + constexpr const volatile S &vrs = s; // ok + static_assert(s.i, ""); + static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(s.v), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}} + static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + + // - a non-volatile glvalue of literal type that refers to a non-volatile + // temporary object whose lifetime has not ended, initialized with a + // constant expression; + constexpr volatile S f() { return S(); } + static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here! + static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} +} + +// DR1312: The proposed wording for this defect has issues, so we ignore this +// bullet and instead prohibit casts from pointers to cv void (see core-20842 +// and core-20845). +// +// - an lvalue-to-rvalue conversion (4.1 [conv.lval]) that is applied to a +// glvalue of type cv1 T that refers to an object of type cv2 U, where T and U +// are neither the same type nor similar types (4.4 [conv.qual]); + +// - an lvalue-to-rvalue conversion (4.1) that is applied to a glvalue that +// refers to a non-active member of a union or a subobject thereof; +namespace LValueToRValueUnion { + // test/SemaCXX/constant-expression-cxx11.cpp contains more thorough testing + // of this. + union U { int a, b; } constexpr u = U(); + static_assert(u.a == 0, ""); + constexpr const int *bp = &u.b; + constexpr int b = *bp; // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}} + + extern const U pu; + constexpr const int *pua = &pu.a; + constexpr const int *pub = &pu.b; + constexpr U pu = { .b = 1 }; // expected-warning {{C99 feature}} + constexpr const int a2 = *pua; // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}} + constexpr const int b2 = *pub; // ok +} + +// - an id-expression that refers to a variable or data member of reference type +// unless the reference has a preceding initialization, initialized with a +// constant expression; +namespace References { + const int a = 2; + int &b = *const_cast<int*>(&a); + int c = 10; // expected-note 2 {{here}} + int &d = c; + constexpr int e = 42; + int &f = const_cast<int&>(e); + extern int &g; + constexpr int &h(); // expected-note {{here}} + int &i = h(); // expected-note {{here}} + constexpr int &j() { return b; } + int &k = j(); + + struct S { + int A : a; + int B : b; + int C : c; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + int D : d; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + int D2 : &d - &c + 1; + int E : e / 2; + int F : f - 11; + int G : g; // expected-error {{constant expression}} + int H : h(); // expected-error {{constant expression}} expected-note {{undefined function 'h'}} + int I : i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}} + int J : j(); + int K : k; + }; +} + +// - a dynamic_cast (5.2.7); +namespace DynamicCast { + struct S { int n; }; + constexpr S s { 16 }; + struct T { + int n : dynamic_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{dynamic_cast}} + }; +} + +// - a reinterpret_cast (5.2.10); +namespace ReinterpretCast { + struct S { int n; }; + constexpr S s { 16 }; + struct T { + int n : reinterpret_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} + }; + struct U { + int m : (long)(S*)6; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} + }; +} + +// - a pseudo-destructor call (5.2.4); +namespace PseudoDtor { + int k; + typedef int I; + struct T { + int n : (k.~I(), 0); // expected-error {{constant expression}} + }; +} + +// - increment or decrement operations (5.2.6, 5.3.2); +namespace IncDec { + int k = 2; + struct T { + int n : ++k; // expected-error {{constant expression}} + int m : --k; // expected-error {{constant expression}} + }; +} + +// - a typeid expression (5.2.8) whose operand is of a polymorphic class type; +namespace std { + struct type_info { + virtual ~type_info(); + const char *name; + }; +} +namespace TypeId { + struct S { virtual void f(); }; + constexpr S *p = 0; + constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} expected-note {{typeid applied to expression of polymorphic type 'TypeId::S'}} + + struct T {} t; + constexpr const std::type_info &ti2 = typeid(t); +} + +// - a new-expression (5.3.4); +// - a delete-expression (5.3.5); +namespace NewDelete { + int *p = 0; + struct T { + int n : *new int(4); // expected-error {{constant expression}} + int m : (delete p, 2); // expected-error {{constant expression}} + }; +} + +// - a relational (5.9) or equality (5.10) operator where the result is +// unspecified; +namespace UnspecifiedRelations { + int a, b; + constexpr int *p = &a, *q = &b; + // C++11 [expr.rel]p2: If two pointers p and q of the same type point to + // different objects that are not members of the same array or to different + // functions, or if only one of them is null, the results of p<q, p>q, p<=q, + // and p>=q are unspecified. + constexpr bool u1 = p < q; // expected-error {{constant expression}} + constexpr bool u2 = p > q; // expected-error {{constant expression}} + constexpr bool u3 = p <= q; // expected-error {{constant expression}} + constexpr bool u4 = p >= q; // expected-error {{constant expression}} + constexpr bool u5 = p < 0; // expected-error {{constant expression}} + constexpr bool u6 = p <= 0; // expected-error {{constant expression}} + constexpr bool u7 = p > 0; // expected-error {{constant expression}} + constexpr bool u8 = p >= 0; // expected-error {{constant expression}} + constexpr bool u9 = 0 < q; // expected-error {{constant expression}} + constexpr bool u10 = 0 <= q; // expected-error {{constant expression}} + constexpr bool u11 = 0 > q; // expected-error {{constant expression}} + constexpr bool u12 = 0 >= q; // expected-error {{constant expression}} + void f(), g(); + + constexpr void (*pf)() = &f, (*pg)() = &g; + constexpr bool u13 = pf < pg; // expected-error {{constant expression}} + constexpr bool u14 = pf == pg; + + // If two pointers point to non-static data members of the same object with + // different access control, the result is unspecified. + struct A { + public: + constexpr A() : a(0), b(0) {} + int a; + constexpr bool cmp() { return &a < &b; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'A' with differing access specifiers (public vs private) has unspecified value}} + private: + int b; + }; + class B { + public: + A a; + constexpr bool cmp() { return &a.a < &b.a; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'B' with differing access specifiers (public vs protected) has unspecified value}} + protected: + A b; + }; + + // If two pointers point to different base sub-objects of the same object, or + // one points to a base subobject and the other points to a member, the result + // of the comparison is unspecified. This is not explicitly called out by + // [expr.rel]p2, but is covered by 'Other pointer comparisons are + // unspecified'. + struct C { + int c[2]; + }; + struct D { + int d; + }; + struct E : C, D { + struct Inner { + int f; + } e; + } e; + constexpr bool base1 = &e.c[0] < &e.d; // expected-error {{constant expression}} expected-note {{comparison of addresses of subobjects of different base classes has unspecified value}} + constexpr bool base2 = &e.c[1] < &e.e.f; // expected-error {{constant expression}} expected-note {{comparison of address of base class subobject 'C' of class 'E' to field 'e' has unspecified value}} + constexpr bool base3 = &e.e.f < &e.d; // expected-error {{constant expression}} expected-note {{comparison of address of base class subobject 'D' of class 'E' to field 'e' has unspecified value}} + + // [expr.rel]p3: Pointers to void can be compared [...] if both pointers + // represent the same address or are both the null pointer [...]; otherwise + // the result is unspecified. + struct S { int a, b; } s; + constexpr void *null = 0; + constexpr void *pv = (void*)&s.a; + constexpr void *qv = (void*)&s.b; + constexpr bool v1 = null < 0; + constexpr bool v2 = null < pv; // expected-error {{constant expression}} + constexpr bool v3 = null == pv; // ok + constexpr bool v4 = qv == pv; // ok + constexpr bool v5 = qv >= pv; // expected-error {{constant expression}} expected-note {{unequal pointers to void}} + constexpr bool v6 = qv > null; // expected-error {{constant expression}} + constexpr bool v7 = qv <= (void*)&s.b; // ok + constexpr bool v8 = qv > (void*)&s.a; // expected-error {{constant expression}} expected-note {{unequal pointers to void}} +} + +// - an assignment or a compound assignment (5.17); or +namespace Assignment { + int k; + struct T { + int n : (k = 9); // expected-error {{constant expression}} + int m : (k *= 2); // expected-error {{constant expression}} + }; + + struct Literal { + constexpr Literal(const char *name) : name(name) {} + const char *name; + }; + struct Expr { + constexpr Expr(Literal l) : IsLiteral(true), l(l) {} + bool IsLiteral; + union { + Literal l; + // ... + }; + }; + struct MulEq { + constexpr MulEq(Expr a, Expr b) : LHS(a), RHS(b) {} + Expr LHS; + Expr RHS; + }; + constexpr MulEq operator*=(Expr a, Expr b) { return MulEq(a, b); } + Literal a("a"); + Literal b("b"); + MulEq c = a *= b; // ok +} + +// - a throw-expression (15.1) +namespace Throw { + struct S { + int n : (throw "hello", 10); // expected-error {{constant expression}} + }; +} // PR9999 -template<bool v> +template<unsigned int v> class bitWidthHolding { public: static const @@ -23,3 +591,6 @@ struct and_or { static const bool and_value = and_or<true>::and_value; static const bool or_value = and_or<true>::or_value; + +static_assert(and_value == false, ""); +static_assert(or_value == true, ""); diff --git a/test/CXX/expr/expr.const/p3-0x-nowarn.cpp b/test/CXX/expr/expr.const/p3-0x-nowarn.cpp new file mode 100644 index 0000000..c891374 --- /dev/null +++ b/test/CXX/expr/expr.const/p3-0x-nowarn.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-c++11-narrowing -verify %s + +// <rdar://problem/11121178> +void f(int x) { + switch (x) { + case 0x80000001: break; + } +} diff --git a/test/CXX/expr/expr.const/p3-0x.cpp b/test/CXX/expr/expr.const/p3-0x.cpp new file mode 100644 index 0000000..6ddd11b --- /dev/null +++ b/test/CXX/expr/expr.const/p3-0x.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// A converted constant expression of type T is a core constant expression, +int nonconst = 8; // expected-note 3 {{here}} +enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}} +template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} +void NonConstF() { + switch (nonconst) { + case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}} + break; + } + return; +} + +// implicitly converted to a prvalue of type T, where the converted expression +// is a literal constant expression + +bool a(int n) { + constexpr char vowels[] = "aeiou"; + switch (n) { + case vowels[0]: + case vowels[1]: + case vowels[2]: + case vowels[3]: + case vowels[4]: + static_assert(!vowels[5], "unexpected number of vowels"); + return true; + } + return false; +} + +// and the implicit conversion sequence contains only +// +// user-defined conversions, +struct S { constexpr operator int() const { return 5; } }; +enum E : unsigned char { E5 = S(), E6, E10 = S() * 2, E1 = E5 / 5 }; + +// lvalue-to-rvalue conversions, +const E e10 = E10; +template<E> struct T {}; +T<e10> s10; + +// integral promotions, and +enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 }; + +// integral conversions other than narrowing conversions +int b(unsigned n) { + switch (n) { + case E6: + case EE::EE32: // expected-error {{not implicitly convertible}} + case (int)EE::EE32: + case 1000: + case (long long)1e10: // expected-error {{case value evaluates to 10000000000, which cannot be narrowed to type 'unsigned int'}} + case -3: // expected-error {{case value evaluates to -3, which cannot be narrowed to type 'unsigned int'}} + return n; + } + return 0; +} +enum class EEE : unsigned short { + a = E6, + b = EE::EE32, // expected-error {{not implicitly convertible}} + c = (int)EE::EE32, + d = 1000, + e = 123456, // expected-error {{enumerator value evaluates to 123456, which cannot be narrowed to type 'unsigned short'}} + f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be narrowed to type 'unsigned short'}} +}; +template<unsigned char> using A = int; +using Int = A<E6>; +using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}} +using Int = A<(int)EE::EE32>; +using Int = A<200>; +using Int = A<1000>; // expected-error {{template argument evaluates to 1000, which cannot be narrowed to type 'unsigned char'}} +using Int = A<-3>; // expected-error {{template argument evaluates to -3, which cannot be narrowed to type 'unsigned char'}} + +// Note, conversions from integral or unscoped enumeration types to bool are +// integral conversions as well as boolean conversions. +template<typename T, T v> struct Val { static constexpr T value = v; }; +static_assert(Val<bool, E1>::value == 1, ""); // ok +static_assert(Val<bool, '\0'>::value == 0, ""); // ok +static_assert(Val<bool, U'\1'>::value == 1, ""); // ok +static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}} + +// (no other conversions are permitted) +using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}} +enum B : bool { + True = &a, // expected-error {{conversion from 'bool (*)(int)' to 'bool' is not allowed in a converted constant expression}} + False = nullptr // expected-error {{conversion from 'nullptr_t' to 'bool' is not allowed in a converted constant expression}} +}; +void c() { + // Note, promoted type of switch is 'int'. + switch (bool b = a(5)) { // expected-warning {{boolean value}} + case 0.0f: // expected-error {{conversion from 'float' to 'int' is not allowed in a converted constant expression}} + break; + } +} +template<bool B> int f() { return B; } +template int f<&S::operator int>(); // expected-error {{does not refer to a function template}} +template int f<(bool)&S::operator int>(); + +int n = Val<bool, &S::operator int>::value; // expected-error {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}} + +namespace NonConstLValue { + struct S { + constexpr operator int() { return 10; } + }; + S s; // not constexpr + // Under the FDIS, this is not a converted constant expression. + // Under the new proposed wording, it is. + enum E : char { e = s }; +} diff --git a/test/CXX/expr/expr.const/p5-0x.cpp b/test/CXX/expr/expr.const/p5-0x.cpp new file mode 100644 index 0000000..60fabe3 --- /dev/null +++ b/test/CXX/expr/expr.const/p5-0x.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// If an expression of literal class type is used in a context where an integral +// constant expression is required, then that class type shall have a single +// non-explicit conversion function to an integral or unscoped enumeration type +namespace std_example { + +struct A { + constexpr A(int i) : val(i) { } + constexpr operator int() { return val; } + constexpr operator long() { return 43; } +private: + int val; +}; +template<int> struct X { }; +constexpr A a = 42; +X<a> x; // ok, unique conversion to int +int ary[a]; // expected-error {{size of array has non-integer type 'const std_example::A'}} + +} + +struct OK { + constexpr OK() {} + constexpr operator int() { return 8; } +} constexpr ok; +extern struct Incomplete incomplete; // expected-note 4{{forward decl}} +struct Explicit { + constexpr Explicit() {} + constexpr explicit operator int() { return 4; } // expected-note 4{{here}} +} constexpr expl; +struct Ambiguous { + constexpr Ambiguous() {} + constexpr operator int() { return 2; } // expected-note 4{{here}} + constexpr operator long() { return 1; } // expected-note 4{{here}} +} constexpr ambig; + +constexpr int test_ok = ok; // ok +constexpr int test_explicit(expl); // ok +constexpr int test_ambiguous = ambig; // ok + +static_assert(test_ok == 8, ""); +static_assert(test_explicit == 4, ""); +static_assert(test_ambiguous == 2, ""); + +// [expr.new]p6: Every constant-expression in a noptr-new-declarator shall be +// an integral constant expression +auto new1 = new int[1][ok]; +auto new2 = new int[1][incomplete]; // expected-error {{incomplete}} +auto new3 = new int[1][expl]; // expected-error {{explicit conversion}} +auto new4 = new int[1][ambig]; // expected-error {{ambiguous conversion}} + +// [dcl.enum]p5: If the underlying type is not fixed [...] the initializing +// value [...] shall be an integral constant expression. +enum NotFixed { + enum1 = ok, + enum2 = incomplete, // expected-error {{incomplete}} + enum3 = expl, // expected-error {{explicit conversion}} + enum4 = ambig // expected-error {{ambiguous conversion}} +}; + +// [dcl.align]p2: When the alignment-specifier is of the form +// alignas(assignment-expression), the assignment-expression shall be an +// integral constant expression +int alignas(ok) alignas1; +int alignas(incomplete) alignas2; // expected-error {{incomplete}} +int alignas(expl) alignas3; // expected-error {{explicit conversion}} +int alignas(ambig) alignas4; // expected-error {{ambiguous conversion}} + +// [dcl.array]p1: If the constant-expression is present, it shall be an integral +// constant expression +// FIXME: The VLA recovery results in us giving diagnostics which aren't great +// here. +int array1[ok]; +int array2[incomplete]; // expected-error {{non-integer type}} +int array3[expl]; // expected-error {{non-integer type}} +int array4[ambig]; // expected-error {{non-integer type}} + +// [class.bit]p1: The constasnt-expression shall be an integral constant +// expression +struct Bitfields { + int bitfield1 : ok; + int bitfield2 : incomplete; // expected-error {{incomplete}} + int bitfield3 : expl; // expected-error {{explicit conversion}} + int bitfield4 : ambig; // expected-error {{ambiguous conversion}} +}; diff --git a/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp b/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp new file mode 100644 index 0000000..253744e --- /dev/null +++ b/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct foo { + foo(); + foo(int); +}; + +int func(foo& f) { + decltype(foo())(); + f = (decltype(foo()))5; + return decltype(3)(5); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp new file mode 100644 index 0000000..249c976 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}} + int *m = &n; // ok + + int n = f(); // ok + int f(); +}; + +int i = sizeof(S::m); // ok +int j = sizeof(S::m + 42); // ok + + +struct T { + int n; + static void f() { + int a[n]; // expected-error {{invalid use of member 'n' in static member function}} + int b[sizeof n]; // ok + } +}; + +// Make sure the rule for unevaluated operands works correctly with typeid. +namespace std { + class type_info; +} +class Poly { virtual ~Poly(); }; +const std::type_info& k = typeid(S::m); +const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of non-static data member}} +const std::type_info& n = typeid(*(Poly*)(0*sizeof S::m)); + +namespace PR11956 { + struct X { char a; }; + struct Y { int f() { return sizeof(X::a); } }; // ok + + struct A { enum E {} E; }; + struct B { int f() { return sizeof(A::E); } }; // ok +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp new file mode 100644 index 0000000..4e57b74 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + S *p = this; // ok + decltype(this) q; // expected-error {{invalid use of 'this' outside of a non-static member function}} + + int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a non-static member function}} + int sz = sizeof(this); // ok +}; + +namespace CaptureThis { + struct X { + int n = 10; + int m = [&]{return n + 1; }(); + int o = [&]{return this->m + 1; }(); + int p = [&]{return [&](int x) { return this->m + x;}(o); }(); + }; + + X x; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp new file mode 100644 index 0000000..5b3a004 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct global { +}; + +namespace PR10127 { + struct outer { + struct middle { + struct inner { + int func(); + int i; + }; + struct inner2 { + }; + struct inner3 { + }; + int mfunc(); + }; + typedef int td_int; + }; + + struct str { + operator decltype(outer::middle::inner()) (); + operator decltype(outer::middle())::inner2 (); + operator decltype(outer())::middle::inner3 (); + str(int (decltype(outer::middle::inner())::*n)(), + int (decltype(outer::middle())::inner::*o)(), + int (decltype(outer())::middle::inner::*p)()); + }; + + decltype(outer::middle::inner()) a; + void scope() { + a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}} + a.decltype(outer::middle::inner())::func(); + a.decltype(outer::middle())::inner::func(); + a.decltype(outer())::middle::inner::func(); + + a.decltype(outer())::middle::inner::~inner(); + + decltype(outer())::middle::inner().func(); + } + decltype(outer::middle())::inner b; + decltype(outer())::middle::inner c; + decltype(outer())::fail d; // expected-error{{no type named 'fail' in 'PR10127::outer'}} + decltype(outer())::fail::inner e; // expected-error{{no member named 'fail' in 'PR10127::outer'}} + decltype()::fail f; // expected-error{{expected expression}} + decltype()::middle::fail g; // expected-error{{expected expression}} + + decltype(int()) h; + decltype(int())::PR10127::outer i; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}} + decltype(int())::global j; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}} + + outer::middle k = decltype(outer())::middle(); + outer::middle::inner l = decltype(outer())::middle::inner(); + + template<typename T> + struct templ { + typename decltype(T())::middle::inner x; // expected-error{{type 'decltype(int())' (aka 'int') cannot be used prior to '::' because it has no members}} + }; + + template class templ<int>; // expected-note{{in instantiation of template class 'PR10127::templ<int>' requested here}} + template class templ<outer>; + + enum class foo { + bar, + baz + }; + + foo m = decltype(foo::bar)::baz; + + enum E { + }; + struct bar { + enum E : decltype(outer())::td_int(4); + enum F : decltype(outer())::td_int; + enum G : decltype; // expected-error{{expected '(' after 'decltype'}} + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm new file mode 100644 index 0000000..0c3fdb2 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++11 -fblocks %s -verify + +void block_capture_errors() { + __block int var; // expected-note 2{{'var' declared here}} + (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} + + (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} +} + +void conversion_to_block(int captured) { + int (^b1)(int) = [=](int x) { return x + captured; }; + + const auto lambda = [=](int x) { return x + captured; }; + int (^b2)(int) = lambda; +} + +template<typename T> +class ConstCopyConstructorBoom { +public: + ConstCopyConstructorBoom(ConstCopyConstructorBoom&); + + ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) { + T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} + } + + void foo() const; +}; + +void conversion_to_block_init(ConstCopyConstructorBoom<int> boom, + ConstCopyConstructorBoom<float> boom2) { + const auto& lambda1([=] { boom.foo(); }); // okay + + const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}} + void (^block)(void) = lambda2; +} + + +void nesting() { + int array[7]; // expected-note 2{{'array' declared here}} + [=] () mutable { + [&] { + ^ { + int i = array[2]; + i += array[3]; + }(); + }(); + }(); + + [&] { + [=] () mutable { + ^ { + int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}} + i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}} + }(); + }(); + }(); +} + +namespace overloading { + void bool_conversion() { + if ([](){}) { + } + + bool b = []{}; + b = (bool)[]{}; + } + + void conversions() { + int (*fp)(int) = [](int x) { return x + 1; }; + fp = [](int x) { return x + 1; }; + + typedef int (*func_ptr)(int); + fp = (func_ptr)[](int x) { return x + 1; }; + + int (^bp)(int) = [](int x) { return x + 1; }; + bp = [](int x) { return x + 1; }; + + typedef int (^block_ptr)(int); + bp = (block_ptr)[](int x) { return x + 1; }; + } + + int &accept_lambda_conv(int (*fp)(int)); + float &accept_lambda_conv(int (^bp)(int)); + + void call_with_lambda() { + int &ir = accept_lambda_conv([](int x) { return x + 1; }); + } +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp new file mode 100644 index 0000000..5dac886 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -Wno-lambda-extensions -verify + +void defargs() { + auto l1 = [](int i, int j = 17, int k = 18) { return i + j + k; }; + int i1 = l1(1); + int i2 = l1(1, 2); + int i3 = l1(1, 2, 3); +} + + +void defargs_errors() { + auto l1 = [](int i, + int j = 17, + int k) { }; // expected-error{{missing default argument on parameter 'k'}} + + auto l2 = [](int i, int j = i) {}; // expected-error{{default argument references parameter 'i'}} + + int foo; + auto l3 = [](int i = foo) {}; // expected-error{{default argument references local variable 'foo' of enclosing function}} +} + +struct NonPOD { + NonPOD(); + NonPOD(const NonPOD&); + ~NonPOD(); +}; + +struct NoDefaultCtor { + NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}} + ~NoDefaultCtor(); +}; + +template<typename T> +void defargs_in_template_unused(T t) { + auto l1 = [](const T& value = T()) { }; + l1(t); +} + +template void defargs_in_template_unused(NonPOD); +template void defargs_in_template_unused(NoDefaultCtor); + +template<typename T> +void defargs_in_template_used() { + auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} + l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}} +} + +template void defargs_in_template_used<NonPOD>(); +template void defargs_in_template_used<NoDefaultCtor>(); // expected-note{{in instantiation of function template specialization}} + diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp new file mode 100644 index 0000000..245e270 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +int GlobalVar; // expected-note {{declared here}} + +namespace N { + int AmbiguousVar; // expected-note {{candidate}} +} +int AmbiguousVar; // expected-note {{candidate}} +using namespace N; + +class X0 { + int Member; + + static void Overload(int); + void Overload(); + virtual X0& Overload(float); + + void explicit_capture() { + int variable; // expected-note {{declared here}} + (void)[&Overload] () {}; // expected-error {{does not name a variable}} + (void)[&GlobalVar] () {}; // expected-error {{does not have automatic storage duration}} + (void)[&AmbiguousVar] () {}; // expected-error {{reference to 'AmbiguousVar' is ambiguous}} + (void)[&Variable] () {}; // expected-error {{use of undeclared identifier 'Variable'; did you mean 'variable'}} + } +}; + +void test_reaching_scope() { + int local; // expected-note{{declared here}} + static int local_static; // expected-note{{'local_static' declared here}} + (void)[=]() { + struct InnerLocal { + void member() { + (void)[local, // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}} + local_static]() { // expected-error{{'local_static' cannot be captured because it does not have automatic storage duration}} + return 0; + }; + } + }; + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp new file mode 100644 index 0000000..d265dd7 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +void test_reaching_scope() { + int local; // expected-note{{declared here}} + static int local_static; + (void)[=]() { + struct InnerLocal { + void member() { + (void)[=]() { + return local + // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}} + local_static; + }; + } + }; + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp new file mode 100644 index 0000000..4a2a4f3 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +void odr_used() { + int i = 17; + [i]{}(); +} + +struct ReachingThis { + static void static_foo() { + (void)[this](){}; // expected-error{{'this' cannot be captured in this context}} + + struct Local { + int i; + + void bar() { + (void)[this](){}; + (void)[&](){i = 7; }; + } + }; + } + + void foo() { + (void)[this](){}; + + struct Local { + int i; + + static void static_bar() { + (void)[this](){}; // expected-error{{'this' cannot be captured in this context}} + (void)[&](){i = 7; }; // expected-error{{invalid use of member 'i' in static member function}} + } + }; + } +}; + +void immediately_enclosing(int i) { // expected-note{{'i' declared here}} + [i]() { + [i] {}(); + }(); + + [=]() { + [i] {}(); + }(); + + []() { // expected-note{{lambda expression begins here}} + [i] {}(); // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} + }(); +} + +void f1(int i) { // expected-note{{declared here}} + int const N = 20; + auto m1 = [=]{ + int const M = 30; + auto m2 = [i]{ + int x[N][M]; + x[0][0] = i; + }; + (void)N; + (void)M; + (void)m2; + }; + struct s1 { + int f; + void work(int n) { // expected-note{{declared here}} + int m = n*n; + int j = 40; // expected-note{{declared here}} + auto m3 = [this,m] { // expected-note 3{{lambda expression begins here}} + auto m4 = [&,j] { // expected-error{{variable 'j' cannot be implicitly captured in a lambda with no capture-default specified}} + int x = n; // expected-error{{variable 'n' cannot be implicitly captured in a lambda with no capture-default specified}} + x += m; + x += i; // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} + x += f; + }; + }; + } + }; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp new file mode 100644 index 0000000..8bb707e --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +void f2() { + int i = 1; + void g1(int = ([i]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g2(int = ([i]{ return 0; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g3(int = ([=]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g4(int = ([=]{ return 0; })()); + void g5(int = ([]{ return sizeof i; })()); +} + +namespace lambda_in_default_args { + int f(int = [] () -> int { int n; return ++n; } ()); + template<typename T> T g(T = [] () -> T { T n; return ++n; } ()); + int k = f() + g<int>(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp new file mode 100644 index 0000000..678fa4b --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +template<typename T> void capture(const T&); + +class NonCopyable { + NonCopyable(const NonCopyable&); // expected-note 2 {{implicitly declared private here}} +public: + void foo() const; +}; + +class NonConstCopy { +public: + NonConstCopy(NonConstCopy&); // expected-note{{would lose const}} +}; + +void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) { + (void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}} + (void)[=] { + ncr.foo(); // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}} + }(); + + [nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}} +} + +struct NonTrivial { + NonTrivial(); + NonTrivial(const NonTrivial &); + ~NonTrivial(); +}; + +struct CopyCtorDefault { + CopyCtorDefault(); + CopyCtorDefault(const CopyCtorDefault&, NonTrivial nt = NonTrivial()); + + void foo() const; +}; + +void capture_with_default_args(CopyCtorDefault cct) { + (void)[=] () -> void { cct.foo(); }; +} + +struct ExpectedArrayLayout { + CopyCtorDefault array[3]; +}; + +void capture_array() { + CopyCtorDefault array[3]; + auto x = [=]() -> void { + capture(array[0]); + }; + static_assert(sizeof(x) == sizeof(ExpectedArrayLayout), "layout mismatch"); +} + +// Check for the expected non-static data members. + +struct ExpectedLayout { + char a; + short b; +}; + +void test_layout(char a, short b) { + auto x = [=] () -> void { + capture(a); + capture(b); + }; + static_assert(sizeof(x) == sizeof(ExpectedLayout), "Layout mismatch!"); +} + +struct ExpectedThisLayout { + ExpectedThisLayout* a; + void f() { + auto x = [this]() -> void {}; + static_assert(sizeof(x) == sizeof(ExpectedThisLayout), "Layout mismatch!"); + } +}; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp new file mode 100644 index 0000000..c4deba9 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +class NonCopyable { + NonCopyable(const NonCopyable&); +}; + +void capture_by_ref(NonCopyable nc, NonCopyable &ncr) { + int array[3]; + (void)[&nc] () -> void {}; + (void)[&ncr] () -> void {}; + (void)[&array] () -> void {}; +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp new file mode 100644 index 0000000..0cf01ad --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + + +struct X { + X(const X&) = delete; // expected-note 2{{explicitly marked deleted}} + X(X&); +}; + +void test_capture(X x) { + [x] { }(); // okay: non-const copy ctor + + [x] { + [x] { // expected-error{{call to deleted constructor of 'X'}} + }(); + }(); + + [x] { + [&x] { + [x] { // expected-error{{call to deleted constructor of 'const X'}} + }(); + }(); + }(); + + int a; + [=]{ + [&] { + int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + }(); + }(); + + [=]{ + [&a] { + [&] { + int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + }(); + }(); + }(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp new file mode 100644 index 0000000..930a4b3 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +void f3() { + float x, &r = x; + int i; + int &ir = i; + const int &irc = i; + + [=,&irc,&ir] { + static_assert(is_same<decltype(((r))), float const&>::value, + "should be const float&"); + static_assert(is_same<decltype(x), float>::value, "should be float"); + static_assert(is_same<decltype((x)), const float&>::value, + "should be const float&"); + static_assert(is_same<decltype(r), float&>::value, "should be float&"); + static_assert(is_same<decltype(ir), int&>::value, "should be int&"); + static_assert(is_same<decltype((ir)), int&>::value, "should be int&"); + static_assert(is_same<decltype(irc), const int&>::value, + "should be const int&"); + static_assert(is_same<decltype((irc)), const int&>::value, + "should be const int&"); + }(); + + [=] { + [=] () mutable { + static_assert(is_same<decltype(x), float>::value, "should be float"); + static_assert(is_same<decltype((x)), float&>::value, + "should be float&"); + }(); + }(); + + [&i] { + static_assert(is_same<decltype((i)), int&>::value, "should be int&"); + }(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp new file mode 100644 index 0000000..6fe3b25 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +struct MoveOnly { + MoveOnly(MoveOnly&&); + MoveOnly(const MoveOnly&); +}; + +template<typename T> T &&move(T&); +void test_special_member_functions(MoveOnly mo, int i) { + auto lambda1 = [i]() { }; // expected-note 2 {{lambda expression begins here}} + + // Default constructor + decltype(lambda1) lambda2; // expected-error{{call to implicitly-deleted default constructor of 'decltype(lambda1)' (aka '<lambda}} + + // Copy assignment operator + lambda1 = lambda1; // expected-error{{overload resolution selected implicitly-deleted copy assignment operator}} + + // Move assignment operator + lambda1 = move(lambda1); + + // Copy constructor + decltype(lambda1) lambda3 = lambda1; + decltype(lambda1) lambda4(lambda1); + + // Move constructor + decltype(lambda1) lambda5 = move(lambda1); + decltype(lambda1) lambda6(move(lambda1)); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp new file mode 100644 index 0000000..c6ed308d --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +// prvalue +void prvalue() { + auto&& x = []()->void { }; + auto& y = []()->void { }; // expected-error{{cannot bind to a temporary of type}} +} + +namespace std { + class type_info; +} + +struct P { + virtual ~P(); +}; + +void unevaluated_operand(P &p, int i) { + int i2 = sizeof([]()->void{}()); // expected-error{{lambda expression in an unevaluated operand}} + const std::type_info &ti1 = typeid([&]() -> P& { return p; }()); + const std::type_info &ti2 = typeid([&]() -> int { return i; }()); // expected-error{{lambda expression in an unevaluated operand}} +} + +template<typename T> +struct Boom { + Boom(const Boom&) { + T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'int'}} + } + void tickle() const; +}; + +void odr_used(P &p, Boom<int> boom_int, Boom<float> boom_float, + Boom<double> boom_double) { + const std::type_info &ti1 + = typeid([=,&p]() -> P& { boom_int.tickle(); return p; }()); // expected-note{{in instantiation of member function 'Boom<int>::Boom' requested here}} + const std::type_info &ti2 + = typeid([=]() -> int { boom_float.tickle(); return 0; }()); // expected-error{{lambda expression in an unevaluated operand}} \ + // expected-note{{in instantiation of member function 'Boom<float>::Boom' requested here}} + + auto foo = [=]() -> int { boom_double.tickle(); return 0; }; // expected-note{{in instantiation of member function 'Boom<double>::Boom' requested here}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp new file mode 100644 index 0000000..4487cfc --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +template<typename T> +void destroy(T* ptr) { + ptr->~T(); + (*ptr).~T(); +} + +void destructor() { + auto lambda = []{}; + destroy(&lambda); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp new file mode 100644 index 0000000..7139058 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +struct DirectInitOnly { + explicit DirectInitOnly(DirectInitOnly&); +}; + +void direct_init_capture(DirectInitOnly &dio) { + [dio] {}(); +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp new file mode 100644 index 0000000..174db25 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void print(); + +template<typename T, typename... Ts> +void print(T first, Ts... rest) { + (void)first; + print(rest...); +} + +template<typename... Ts> +void unsupported(Ts ...values) { + auto unsup = [values] {}; // expected-error{{unexpanded function parameter pack capture is unsupported}} +} + +template<typename... Ts> +void implicit_capture(Ts ...values) { + auto implicit = [&] { print(values...); }; + implicit(); +} + +template<typename... Ts> +void do_print(Ts... values) { + auto bycopy = [values...]() { print(values...); }; + bycopy(); + auto byref = [&values...]() { print(values...); }; + byref(); + + auto bycopy2 = [=]() { print(values...); }; + bycopy2(); + auto byref2 = [&]() { print(values...); }; + byref2(); +} + +template void do_print(int, float, double); + +template<typename T, int... Values> +void bogus_expansions(T x) { + auto l1 = [x...] {}; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + auto l2 = [Values...] {}; // expected-error{{'Values' in capture list does not name a variable}} +} + +void g(int*, float*, double*); + +template<class... Args> +void std_example(Args... args) { + auto lm = [&, args...] { return g(args...); }; +}; + +template void std_example(int*, float*, double*); + +template<typename ...Args> +void variadic_lambda(Args... args) { + auto lambda = [](Args... inner_args) { return g(inner_args...); }; + lambda(args...); +} + +template void variadic_lambda(int*, float*, double*); diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp new file mode 100644 index 0000000..562f92a --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void test_nonaggregate(int i) { + auto lambda = [i]() -> void {}; // expected-note 3{{candidate constructor}} + decltype(lambda) foo = { 1 }; // expected-error{{no matching constructor}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp new file mode 100644 index 0000000..d816e17 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void missing_lambda_declarator() { + [](){}(); +} + +template<typename T> T get(); + +void infer_void_return_type(int i) { + if (i > 17) + return []() { }(); + + if (i > 11) + return []() { return; }(); + + return [](int x) { + switch (x) { + case 0: return get<void>(); + case 1: return; + case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}} + } + }(7); +} + +struct X { }; + +X infer_X_return_type(X x) { + return [&x](int y) { // expected-warning{{omitted result type}} + if (y > 0) + return X(); + else + return x; + }(5); +} + +X infer_X_return_type_fail(X x) { + return [x](int y) { // expected-warning{{omitted result type}} + if (y > 0) + return X(); + else + return x; // expected-error{{return type 'const X' must match previous return type 'X' when lambda expression has unspecified explicit return type}} + }(5); +} + +struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} +void test_result_type(int N) { + auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}} + + typedef int vla[N]; + auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int [N]')}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm new file mode 100644 index 0000000..0126e23 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +@interface A +@end + +void test_result_type() { + auto l1 = [] () -> A { }; // expected-error{{non-pointer Objective-C class type 'A' in lambda expression result}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp new file mode 100644 index 0000000..68460f0 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -std=c++11 %s -Winvalid-noreturn -verify + +// An attribute-specifier-seq in a lambda-declarator appertains to the +// type of the corresponding function call operator. +void test_attributes() { + auto nrl = [](int x) -> int { if (x > 0) return x; }; // expected-warning{{control may reach end of non-void lambda}} + + auto nrl2 = []() [[noreturn]] { return; }; // expected-error{{lambda declared 'noreturn' should not return}} +} + +template<typename T> +struct bogus_override_if_virtual : public T { + bogus_override_if_virtual() : T(*(T*)0) { } + int operator()() const; +}; + +void test_quals() { + // This function call operator is declared const (9.3.1) if and only + // if the lambda- expression's parameter-declaration-clause is not + // followed by mutable. + auto l = [=](){}; // expected-note{{method is not marked volatile}} + const decltype(l) lc = l; + l(); + lc(); + + auto ml = [=]() mutable{}; // expected-note{{method is not marked const}} \ + // expected-note{{method is not marked volatile}} + const decltype(ml) mlc = ml; + ml(); + mlc(); // expected-error{{no matching function for call to object of type}} + + // It is neither virtual nor declared volatile. + volatile decltype(l) lv = l; + volatile decltype(ml) mlv = ml; + lv(); // expected-error{{no matching function for call to object of type}} + mlv(); // expected-error{{no matching function for call to object of type}} + + bogus_override_if_virtual<decltype(l)> bogus; +} + +// Default arguments (8.3.6) shall not be specified in the +// parameter-declaration-clause of a lambda- declarator. +// Note: Removed by core issue 974. +int test_default_args() { + return [](int i = 5, // expected-warning{{C++11 forbids default arguments for lambda expressions}} + int j = 17) { return i+j;}(5, 6); +} + +// Any exception-specification specified on a lambda-expression +// applies to the corresponding function call operator. +void test_exception_spec() { + auto tl1 = []() throw(int) {}; + auto tl2 = []() {}; + static_assert(!noexcept(tl1()), "lambda can throw"); + static_assert(!noexcept(tl2()), "lambda can throw"); + + auto ntl1 = []() throw() {}; + auto ntl2 = []() noexcept(true) {}; + auto ntl3 = []() noexcept {}; + static_assert(noexcept(ntl1()), "lambda cannot throw"); + static_assert(noexcept(ntl2()), "lambda cannot throw"); + static_assert(noexcept(ntl3()), "lambda cannot throw"); +} + diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp new file mode 100644 index 0000000..8b43cef --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void test_conversion() { + int (*fp1)(int) = [](int x) { return x + 1; }; + void (*fp2)(int) = [](int x) { }; + + const auto lambda = [](int x) { }; + void (*fp3)(int) = lambda; + + volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}} + void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}} +} + +void test_no_conversion() { + int (*fp1)(int) = [=](int x) { return x + 1; }; // expected-error{{no viable conversion}} + void (*fp2)(int) = [&](int x) { }; // expected-error{{no viable conversion}} +} + +void test_wonky() { + const auto l = [](int x) mutable -> int { return + 1; }; + l(17); // okay: uses conversion function +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp new file mode 100644 index 0000000..9dbe2e1 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +// Check that analysis-based warnings work in lambda bodies. +void analysis_based_warnings() { + (void)[]() -> int { }; // expected-warning{{control reaches end of non-void lambda}} +} + +// Check that we get the right types of captured variables (the +// semantic-analysis part of p7). +int &check_const_int(int&); +float &check_const_int(const int&); + +void test_capture_constness(int i, const int ic) { + (void)[i,ic] ()->void { + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + (void)[=] ()->void { + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + (void)[i,ic] () mutable ->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[=] () mutable ->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[&i,&ic] ()->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[&] ()->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; +} + + +struct S1 { + int x, y; + S1 &operator=(int*); + int operator()(int); + void f() { + [&]()->int { + S1 &s1 = operator=(&this->x); + return operator()(this->x + y); + }(); + } +}; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp new file mode 100644 index 0000000..d1384f1 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +class X0 { + void explicit_capture() { + int foo; + + (void)[foo, foo] () {}; // expected-error {{'foo' can appear only once}} + (void)[this, this] () {}; // expected-error {{'this' can appear only once}} + (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}} + (void)[=, &foo] () {}; + (void)[=, this] () {}; // expected-error {{'this' cannot be explicitly captured}} + (void)[&, foo] () {}; + (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}} + (void)[&, this] () {}; + } +}; + +struct S2 { + void f(int i); + void g(int i); +}; + +void S2::f(int i) { + (void)[&, i]{ }; + (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}} + (void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}} + (void)[=]{ this->g(i); }; + (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp new file mode 100644 index 0000000..49b9c66 --- /dev/null +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify + +template<typename T> +void test_attributes() { + auto nrl = []() [[noreturn]] {}; // expected-error{{lambda declared 'noreturn' should not return}} +} + +template void test_attributes<int>(); // expected-note{{in instantiation of function}} + +template<typename T> +void call_with_zero() { + [](T *ptr) -> T& { return *ptr; }(0); +} + +template void call_with_zero<int>(); + +template<typename T> +T captures(T x, T y) { + auto lambda = [=, &y] () -> T { + T i = x; + return i + y; + }; + + return lambda(); +} + +struct X { + X(const X&); +}; + +X operator+(X, X); +X operator-(X, X); + +template int captures(int, int); +template X captures(X, X); + +template<typename T> +int infer_result(T x, T y) { + auto lambda = [=](bool b) { return x + y; }; + return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}} +} + +template int infer_result(int, int); +template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}} + +// Make sure that lambda's operator() can be used from templates. +template<typename F> +void accept_lambda(F f) { + f(1); +} + +template<typename T> +void pass_lambda(T x) { + accept_lambda([&x](T y) { return x + y; }); +} + +template void pass_lambda(int); + +namespace std { + class type_info; +} + +namespace p2 { + struct P { + virtual ~P(); + }; + + template<typename T> + struct Boom { + Boom(const Boom&) { + T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} + } + void tickle() const; + }; + + template<typename R, typename T> + void odr_used(R &r, Boom<T> boom) { + const std::type_info &ti + = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}} + boom.tickle(); // expected-note{{in instantiation of member function}} + return r; + }()); + } + + template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}} + + template<typename R, typename T> + void odr_used2(R &r, Boom<T> boom) { + const std::type_info &ti + = typeid([=,&r] () -> R& { + boom.tickle(); // expected-note{{in instantiation of member function}} + return r; + }()); + } + + template void odr_used2(P&, Boom<float>); +} + +namespace p5 { + struct NonConstCopy { + NonConstCopy(const NonConstCopy&) = delete; + NonConstCopy(NonConstCopy&); + }; + + template<typename T> + void double_capture(T &nc) { + [=] () mutable { + [=] () mutable { + T nc2(nc); + }(); + }(); + } + + template void double_capture(NonConstCopy&); +} + +namespace NonLocalLambdaInstantation { + template<typename T> + struct X { + static int value; + }; + + template<typename T> + int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}} + + template int X<int>::value; + template int X<float>::value; + template int X<int*>::value; // expected-note{{in instantiation of static data member }} + + template<typename T> + void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \ + // expected-note{{passing argument to parameter 'x' here}} + + void call_defaults() { + defaults<int>(); + defaults<float>(); + defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}} + } + + template<typename T> + struct X2 { + int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}} + }; + + X2<int> x2i; + X2<float> x2f; + X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}} +} diff --git a/test/CXX/expr/expr.prim/p12-0x.cpp b/test/CXX/expr/expr.prim/p12-0x.cpp deleted file mode 100644 index aec62dd..0000000 --- a/test/CXX/expr/expr.prim/p12-0x.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s - -struct S { - int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}} - int *m = &n; // ok - - int n = f(); // ok - int f(); -}; - -int i = sizeof(S::m); // ok -int j = sizeof(S::m + 42); // ok diff --git a/test/CXX/expr/expr.prim/p4-0x.cpp b/test/CXX/expr/expr.prim/p4-0x.cpp deleted file mode 100644 index 143ba89..0000000 --- a/test/CXX/expr/expr.prim/p4-0x.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s - -struct S { - S *p = this; // ok - decltype(this) q; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} \ - expected-error {{C++ requires a type specifier for all declarations}} - - int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a nonstatic member function}} - int sz = sizeof(this); // ok -}; diff --git a/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp b/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp new file mode 100644 index 0000000..27b915e --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -emit-llvm-only %s + +// this used to crash due to templ<int>'s dtor not being marked as used by the +// new expression in func() +struct non_trivial { + non_trivial() {} + ~non_trivial() {} +}; +template < typename T > class templ { + non_trivial n; +}; +void func() { + new templ<int>[1][1]; +} diff --git a/test/CXX/expr/expr.unary/expr.new/p17.cpp b/test/CXX/expr/expr.unary/expr.new/p17.cpp new file mode 100644 index 0000000..0d108eb --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p17.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class ctor { + ctor(); // expected-note{{implicitly declared private here}} +}; + +class dtor { + ~dtor(); // expected-note 3 {{implicitly declared private here}} +}; + +void test() { + new ctor[0]; // expected-error{{calling a private constructor of class 'ctor'}} + new dtor[0]; // expected-error{{calling a private destructor of class 'dtor'}} + new dtor[3]; // expected-error{{calling a private destructor of class 'dtor'}} + new dtor[3][3]; // expected-error{{calling a private destructor of class 'dtor'}} +} diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp new file mode 100644 index 0000000..2dd6b23 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify + +namespace rdar10544564 { + // Check that we don't attempt to use an overloaded operator& when + // naming a pointer-to-member. + struct X { + void** operator & (); + }; + + struct Y + { + public: + X member; + X memfunc1(); + X memfunc2(); + X memfunc2(int); + + void test() { + X Y::*data_mem_ptr = &Y::member; + X (Y::*func_mem_ptr1)() = &Y::memfunc1; + X (Y::*func_mem_ptr2)() = &Y::memfunc2; + } + }; + + X Y::*data_mem_ptr = &Y::member; + X (Y::*func_mem_ptr1)() = &Y::memfunc1; + X (Y::*func_mem_ptr2)() = &Y::memfunc2; +} |