diff options
author | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
---|---|---|
committer | Carlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au> | 2012-10-15 17:10:06 +1100 |
commit | be1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch) | |
tree | 1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/test/CXX/expr | |
parent | c4626a62754862d20b41e8a46a3574264ea80e6d (diff) | |
parent | f1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff) |
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/test/CXX/expr')
61 files changed, 3098 insertions, 0 deletions
diff --git a/clang/test/CXX/expr/expr.ass/p9-cxx11.cpp b/clang/test/CXX/expr/expr.ass/p9-cxx11.cpp new file mode 100644 index 0000000..206c82c --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.cast/p4-0x.cpp b/clang/test/CXX/expr/expr.cast/p4-0x.cpp new file mode 100644 index 0000000..96bf5f9 --- /dev/null +++ b/clang/test/CXX/expr/expr.cast/p4-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct X { }; +struct Y : X { }; + +void test_lvalue_to_rvalue_drop_cvquals(const X &x, const Y &y, const int &i) { + (void)(X&&)x; + (void)(int&&)i; + (void)(X&&)y; + (void)(Y&&)x; +} diff --git a/clang/test/CXX/expr/expr.cast/p4.cpp b/clang/test/CXX/expr/expr.cast/p4.cpp new file mode 100644 index 0000000..907e008 --- /dev/null +++ b/clang/test/CXX/expr/expr.cast/p4.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s + +struct A { int x; }; +struct B { int y; }; +struct C : A, B { }; + +// CHECK: casting_away_constness +void casting_away_constness(const B &b, const C &c, const B *bp, const C *cp) { + // CHECK: DerivedToBase (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'c' + (void)(B&)c; + // CHECK: BaseToDerived (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'b' + (void)(C&)b; + // CHECK: DerivedToBase (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'cp' + (void)(B*)cp; + // CHECK: BaseToDerived (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'bp' + (void)(C*)bp; + // CHECK: ReturnStmt + return; +} diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp new file mode 100644 index 0000000..054669e --- /dev/null +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -0,0 +1,596 @@ +// 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<unsigned int v> +class bitWidthHolding { +public: + static const + unsigned int width = (v == 0 ? 0 : bitWidthHolding<(v >> 1)>::width + 1); +}; + +static const int width=bitWidthHolding<255>::width; + +template<bool b> +struct always_false { + static const bool value = false; +}; + +template<bool b> +struct and_or { + static const bool and_value = b && and_or<always_false<b>::value>::and_value; + static const bool or_value = !b || and_or<always_false<b>::value>::or_value; +}; + +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/clang/test/CXX/expr/expr.const/p3-0x-nowarn.cpp b/clang/test/CXX/expr/expr.const/p3-0x-nowarn.cpp new file mode 100644 index 0000000..c891374 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp new file mode 100644 index 0000000..6ddd11b --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.const/p5-0x.cpp b/clang/test/CXX/expr/expr.const/p5-0x.cpp new file mode 100644 index 0000000..60fabe3 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.mptr.oper/p5.cpp b/clang/test/CXX/expr/expr.mptr.oper/p5.cpp new file mode 100644 index 0000000..7380b5d --- /dev/null +++ b/clang/test/CXX/expr/expr.mptr.oper/p5.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X0 { + void f0(); + void f1() const; + void f2() volatile; + void f3() const volatile; +}; + +void test_object_cvquals(void (X0::*pm)(), + void (X0::*pmc)() const, + void (X0::*pmv)() volatile, + void (X0::*pmcv)() const volatile, + X0 *p, + const X0 *pc, + volatile X0 *pv, + const volatile X0 *pcv, + X0 &o, + const X0 &oc, + volatile X0 &ov, + const volatile X0 &ocv) { + (p->*pm)(); + (p->*pmc)(); + (p->*pmv)(); + (p->*pmcv)(); + + (pc->*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const' qualifier}} + (pc->*pmc)(); + (pc->*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (pc->*pmcv)(); + + (pv->*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'volatile' qualifier}} + (pv->*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (pv->*pmv)(); + (pv->*pmcv)(); + + (pcv->*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const volatile' qualifiers}} + (pcv->*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (pcv->*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (pcv->*pmcv)(); + + (o.*pm)(); + (o.*pmc)(); + (o.*pmv)(); + (o.*pmcv)(); + + (oc.*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const' qualifier}} + (oc.*pmc)(); + (oc.*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (oc.*pmcv)(); + + (ov.*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'volatile' qualifier}} + (ov.*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (ov.*pmv)(); + (ov.*pmcv)(); + + (ocv.*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const volatile' qualifiers}} + (ocv.*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (ocv.*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (ocv.*pmcv)(); +} diff --git a/clang/test/CXX/expr/expr.mptr.oper/p6-0x.cpp b/clang/test/CXX/expr/expr.mptr.oper/p6-0x.cpp new file mode 100644 index 0000000..917b2da --- /dev/null +++ b/clang/test/CXX/expr/expr.mptr.oper/p6-0x.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct X { }; + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); +template<typename T> T prvalue(); + +// In a .* expression whose object expression is an rvalue, the +// program is ill-formed if the second operand is a pointer to member +// function with ref-qualifier &. In a ->* expression or in a .* +// expression whose object expression is an lvalue, the program is +// ill-formed if the second operand is a pointer to member function +// with ref-qualifier &&. +void test(X *xp, int (X::*pmf)(int), int (X::*l_pmf)(int) &, + int (X::*r_pmf)(int) &&) { + // No ref-qualifier. + (lvalue<X>().*pmf)(17); + (xvalue<X>().*pmf)(17); + (prvalue<X>().*pmf)(17); + (xp->*pmf)(17); + + // Lvalue ref-qualifier. + (lvalue<X>().*l_pmf)(17); + (xvalue<X>().*l_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &' can only be called on an lvalue}} + (prvalue<X>().*l_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &' can only be called on an lvalue}} + (xp->*l_pmf)(17); + + // Rvalue ref-qualifier. + (lvalue<X>().*r_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &&' can only be called on an rvalue}} + (xvalue<X>().*r_pmf)(17); + (prvalue<X>().*r_pmf)(17); + (xp->*r_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &&' can only be called on an rvalue}} +} diff --git a/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp b/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp new file mode 100644 index 0000000..d51ba09 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct X1 { + X1(); +}; + +struct X2 { + X2(); + ~X2(); +}; + +void vararg(...); + +void f(X1 x1, X2 x2) { + vararg(x1); // okay + vararg(x2); // expected-error{{cannot pass object of non-trivial type 'X2' through variadic function; call will abort at runtime}} +} + + +namespace PR11131 { + struct S; + + S &getS(); + + void f(...); + + void g() { + (void)sizeof(f(getS())); + } +} diff --git a/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp new file mode 100644 index 0000000..6ba8d51 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// The result of the expression const_cast<T>(v) is of type T. If T is +// an lvalue reference to object type, the result is an lvalue; if T +// is an rvalue reference to object type, the result is an xvalue;. + +unsigned int f(int); + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); +template<typename T> T prvalue(); + +void test_classification(const int *ptr) { + int *ptr0 = const_cast<int *&&>(ptr); + int *ptr1 = const_cast<int *&&>(xvalue<const int*>()); + int *ptr2 = const_cast<int *&&>(prvalue<const int*>()); +} diff --git a/clang/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp b/clang/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp new file mode 100644 index 0000000..cddd5cf --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct X { virtual ~X(); }; +struct Y : public X { }; +struct Z; // expected-note{{forward declaration of 'Z'}} + +void test(X &x, Y &y, Z &z) { + // If T is an rvalue reference type, v shall be an expression having + // a complete class type, and the result is an xvalue of the type + // referred to by T. + Y &&yr0 = dynamic_cast<Y&&>(x); + Y &&yr1 = dynamic_cast<Y&&>(static_cast<X&&>(x)); + Y &&yr2 = dynamic_cast<Y&&>(z); // expected-error{{'Z' is an incomplete type}} +} diff --git a/clang/test/CXX/expr/expr.post/expr.ref/p3.cpp b/clang/test/CXX/expr/expr.post/expr.ref/p3.cpp new file mode 100644 index 0000000..98771d3 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.ref/p3.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +template<typename T> struct Node { + int lhs; + void splay( ) + { + Node<T> n[1]; + (void)n->lhs; + } +}; + +void f() { + Node<int> n; + return n.splay(); +} diff --git a/clang/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp new file mode 100644 index 0000000..22892a6 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If T is an lvalue reference type or an rvalue reference to function +// type, the result is an lvalue; if T is an rvalue reference to +// object type, the result is an xvalue; + +unsigned int f(int); + +template<typename T> T&& xvalue(); +void test_classification(char *ptr) { + int (&fr0)(int) = reinterpret_cast<int (&&)(int)>(f); + int &&ir0 = reinterpret_cast<int &&>(*ptr); + int &&ir1 = reinterpret_cast<int &&>(0); + int &&ir2 = reinterpret_cast<int &&>('a'); + int &&ir3 = reinterpret_cast<int &&>(xvalue<char>()); +} diff --git a/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp new file mode 100644 index 0000000..9ef15e6 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to +// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1" (8.5.3). +struct A { }; +struct B : A { }; + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); + +void test(A &a, B &b) { + A &&ar0 = static_cast<A&&>(a); + A &&ar1 = static_cast<A&&>(b); + A &&ar2 = static_cast<A&&>(lvalue<A>()); + A &&ar3 = static_cast<A&&>(lvalue<B>()); + A &&ar4 = static_cast<A&&>(xvalue<A>()); + A &&ar5 = static_cast<A&&>(xvalue<B>()); + const A &&ar6 = static_cast<const A&&>(a); + const A &&ar7 = static_cast<const A&&>(b); + const A &&ar8 = static_cast<const A&&>(lvalue<A>()); + const A &&ar9 = static_cast<const A&&>(lvalue<B>()); + const A &&ar10 = static_cast<const A&&>(xvalue<A>()); + const A &&ar11 = static_cast<const A&&>(xvalue<B>()); +} diff --git a/clang/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp b/clang/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp new file mode 100644 index 0000000..731c508 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +enum class EC { ec1 }; + +void test0(EC ec) { + (void)static_cast<bool>(ec); + (void)static_cast<bool>(EC::ec1); + (void)static_cast<char>(ec); + (void)static_cast<char>(EC::ec1); + (void)static_cast<int>(ec); + (void)static_cast<int>(EC::ec1); + (void)static_cast<unsigned long>(ec); + (void)static_cast<unsigned long>(EC::ec1); + (void)static_cast<float>(ec); + (void)static_cast<float>(EC::ec1); + (void)static_cast<double>(ec); + (void)static_cast<double>(EC::ec1); +} + +namespace PR9107 { + enum E {}; + template <class _Tp> inline _Tp* addressof(_Tp& __x) { + return (_Tp*)&(char&)__x; + } + void test() { + E a; + addressof(a); + } +} diff --git a/clang/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp new file mode 100644 index 0000000..253744e --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp new file mode 100644 index 0000000..249c976 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp new file mode 100644 index 0000000..030c90c --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +struct A { + int &f(int*); + float &f(int*) const noexcept; + + int *ptr; + auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(this->ptr)); + auto g2() const noexcept(noexcept(f((*this).ptr))) -> decltype(f(ptr)); +}; + +void testA(A &a) { + int &ir = a.g1(); + float &fr = a.g2(); + static_assert(!noexcept(a.g1()), "exception-specification failure"); + static_assert(noexcept(a.g2()), "exception-specification failure"); +} + +struct B { + char g(); + template<class T> auto f(T t) -> decltype(t + g()) + { return t + g(); } +}; + +template auto B::f(int t) -> decltype(t + g()); + +template<typename T> +struct C { + int &f(T*); + float &f(T*) const noexcept; + + T* ptr; + auto g1() noexcept(noexcept(f(ptr))) -> decltype(f((*this).ptr)); + auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr)); +}; + +void test_C(C<int> ci) { + int *p = 0; + int &ir = ci.g1(); + float &fr = ci.g2(); + static_assert(!noexcept(ci.g1()), "exception-specification failure"); + static_assert(noexcept(ci.g2()), "exception-specification failure"); +} + +namespace PR10036 { + template <class I> + void + iter_swap(I x, I y) noexcept; + + template <class T> + class A + { + T t_; + public: + void swap(A& a) noexcept(noexcept(iter_swap(&t_, &a.t_))); + }; + + void test() { + A<int> i, j; + i.swap(j); + } +} + +namespace Static { + struct X1 { + int m; + static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}} + static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}} + + static int h(); + + static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}} + }; + + auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}} + + template<typename T> + struct X2 { + int m; + + T f(T*); + static T f(int); + + auto g(T x) -> decltype(f(x)) { return 0; } + }; + + void test_X2() { + X2<int>().g(0); + } +} + +namespace PR12564 { + struct Base { + void bar(Base&) {} // unexpected-note {{here}} + }; + + struct Derived : Base { + // FIXME: This should be accepted. + void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // unexpected-error {{cannot bind to a value of unrelated type}} + }; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp new file mode 100644 index 0000000..4e57b74 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp new file mode 100644 index 0000000..5b3a004 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm new file mode 100644 index 0000000..0c3fdb2 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp new file mode 100644 index 0000000..5dac886 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp new file mode 100644 index 0000000..245e270 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp new file mode 100644 index 0000000..d265dd7 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp new file mode 100644 index 0000000..4a2a4f3 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp new file mode 100644 index 0000000..8bb707e --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp new file mode 100644 index 0000000..678fa4b --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp new file mode 100644 index 0000000..c4deba9 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp new file mode 100644 index 0000000..0cf01ad --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp new file mode 100644 index 0000000..930a4b3 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp new file mode 100644 index 0000000..6fe3b25 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp new file mode 100644 index 0000000..c6ed308 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp new file mode 100644 index 0000000..4487cfc --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp new file mode 100644 index 0000000..7139058 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp new file mode 100644 index 0000000..174db25 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp new file mode 100644 index 0000000..562f92a --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp new file mode 100644 index 0000000..d816e17 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm new file mode 100644 index 0000000..0126e23 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp new file mode 100644 index 0000000..68460f0 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp new file mode 100644 index 0000000..8b43cef --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp new file mode 100644 index 0000000..9dbe2e1 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp new file mode 100644 index 0000000..d1384f1 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp new file mode 100644 index 0000000..49b9c66 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.unary/expr.delete/p5.cpp b/clang/test/CXX/expr/expr.unary/expr.delete/p5.cpp new file mode 100644 index 0000000..ecb2918 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.delete/p5.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -verify %s + +// If the object being deleted has incomplete class type at the point of +// deletion and the complete class has a non-trivial destructor or a +// deallocation function, the behavior is undefined. + +// The trivial case. +class T0; // expected-note {{forward declaration}} +void f0(T0 *a) { delete a; } // expected-warning {{deleting pointer to incomplete type}} +class T0 { ~T0(); }; + +// The trivial case, inside a template instantiation. +template<typename T> +struct T1_A { T *x; ~T1_A() { delete x; } }; // expected-warning {{deleting pointer to incomplete type}} +class T1_B; // expected-note {{forward declaration}} +void f0() { T1_A<T1_B> x; } // expected-note {{in instantiation of member function}} + +// This case depends on when we check T2_C::f0. +class T2_A; +template<typename T> +struct T2_B { void f0(T *a) { delete a; } }; +struct T2_C { T2_B<T2_A> x; void f0(T2_A *a) { x.f0(a); } }; +void f0(T2_A *a) { T2_C x; x.f0(a); } +class T2_A { }; + +// An alternate version of the same. +class T3_A; +template<typename T> +struct T3_B { + void f0(T *a) { + delete a; // expected-error{{calling a private destructor of class 'T3_A'}} + } +}; + +struct T3_C { + T3_B<T3_A> x; + void f0(T3_A *a) { + x.f0(a); // expected-note{{in instantiation of member function 'T3_B<T3_A>::f0' requested here}} + } +}; + +void f0(T3_A *a) { T3_C x; x.f0(a); } +class T3_A { +private: + ~T3_A(); // expected-note{{declared private here}} +}; diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp new file mode 100644 index 0000000..27b915e --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.unary/expr.new/p17.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p17.cpp new file mode 100644 index 0000000..0d108eb --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.unary/expr.new/p19.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p19.cpp new file mode 100644 index 0000000..bb69fd5 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p19.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions %s +typedef __SIZE_TYPE__ size_t; + +// Operator delete template for placement new with global lookup +template<int I> +struct X0 { + X0(); + + static void* operator new(size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X0() { + // Using the global operator new suppresses the search for a + // operator delete in the class. + ::new X0<2>; + + new X0<3>; // expected-note 2{{instantiation}} +} + +// Operator delete template for placement new[] with global lookup +template<int I> +struct X1 { + X1(); + + static void* operator new[](size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete[](void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X1() { + // Using the global operator new suppresses the search for a + // operator delete in the class. + ::new X1<2> [17]; + + new X1<3> [17]; // expected-note 2{{instantiation}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp new file mode 100644 index 0000000..4ebbfce --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +template<typename T> +struct only { + only(T); + template<typename U> only(U) = delete; +}; + +void f() { + only<const int*> p = new const auto (0); + only<double*> q = new (auto) (0.0); + + new auto; // expected-error{{new expression for type 'auto' requires a constructor argument}} + new (const auto)(); // expected-error{{new expression for type 'auto const' requires a constructor argument}} + new (auto) (1,2,3); // expected-error{{new expression for type 'auto' contains multiple constructor arguments}} +} + +void p2example() { + only<int*> r = new auto(1); + auto x = new auto('a'); + + only<char*> testX = x; +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp new file mode 100644 index 0000000..eca1ec7 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fexceptions %s +typedef __SIZE_TYPE__ size_t; + +struct S { + // Placement allocation function: + static void* operator new(size_t, size_t); + // Usual (non-placement) deallocation function: + static void operator delete(void*, size_t); // expected-note{{declared here}} +}; + +void testS() { + S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p20.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p20.cpp new file mode 100644 index 0000000..8cbe2b9 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p20.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions %s +typedef __SIZE_TYPE__ size_t; + +// Overloaded operator delete with two arguments +template<int I> +struct X0 { + X0(); + static void* operator new(size_t); + static void operator delete(void*, size_t) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X0() { + new X0<1>; // expected-note{{instantiation}} +} + +// Overloaded operator delete with one argument +template<int I> +struct X1 { + X1(); + + static void* operator new(size_t); + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X1() { + new X1<1>; // expected-note{{instantiation}} +} + +// Overloaded operator delete for placement new +template<int I> +struct X2 { + X2(); + + static void* operator new(size_t, double, double); + static void* operator new(size_t, int, int); + + static void operator delete(void*, const int, int) { + int *ip = I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*, double, double); +}; + +void test_X2() { + new (0, 0) X2<1>; // expected-note{{instantiation}} +} + +// Operator delete template for placement new +struct X3 { + X3(); + + static void* operator new(size_t, double, double); + + template<typename T> + static void operator delete(void*, T x, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} + } +}; + +void test_X3() { + new (0, 0) X3; // expected-note{{instantiation}} +} + +// Operator delete template for placement new in global scope. +struct X4 { + X4(); + static void* operator new(size_t, double, double); +}; + +template<typename T> +void operator delete(void*, T x, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} +} + +void test_X4() { + new (0, 0) X4; // expected-note{{instantiation}} +} + +// Useless operator delete hides global operator delete template. +struct X5 { + X5(); + static void* operator new(size_t, double, double); + void operator delete(void*, double*, double*); +}; + +void test_X5() { + new (0, 0) X5; // okay, we found X5::operator delete but didn't pick it +} + +// Operator delete template for placement new +template<int I> +struct X6 { + X6(); + + static void* operator new(size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X6() { + new X6<3>; // expected-note 2{{instantiation}} +} + +void *operator new(size_t, double, double, double); + +template<typename T> +void operator delete(void*, T x, T, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} +} +void test_int_new() { + new (1.0, 1.0, 1.0) int; // expected-note{{instantiation}} +} + +// We don't need an operator delete if the type has a trivial +// constructor, since we know that constructor cannot throw. +// FIXME: Is this within the standard? Seems fishy, but both EDG+GCC do it. +#if 0 +template<int I> +struct X7 { + static void* operator new(size_t); + static void operator delete(void*, size_t) { + int *ip = I; // okay, since it isn't instantiated. + } +}; + +void test_X7() { + new X7<1>; +} +#endif + diff --git a/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp b/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp new file mode 100644 index 0000000..afd8ef0 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Test parsing + semantic analysis +template<typename ...Types> struct count_types { + static const unsigned value = sizeof...(Types); +}; + +template<int ...Values> struct count_ints { + static const unsigned value = sizeof...(Values); +}; + +// Test instantiation +int check_types[count_types<short, int, long>::value == 3? 1 : -1]; +int check_ints[count_ints<1, 2, 3, 4, 5>::value == 5? 1 : -1]; + +// Test instantiation involving function parameter packs. +struct any { + template<typename T> any(T); +}; + +template<typename ...Inits> +void init_me(Inits ...inits) { + any array[sizeof...(inits)] = { inits... }; +} + +template void init_me<int, float, double*>(int, float, double*); + +// Test parser and semantic recovery. +template<int Value> struct count_ints_2 { + static const unsigned value = sizeof...(Value); // expected-error{{'Value' does not refer to the name of a parameter pack}} +}; + +template<typename ...Types> // expected-note{{parameter pack 'Types' declared here}} +struct count_types_2 { + static const unsigned value = sizeof... Type; // expected-error{{missing parentheses around the size of parameter pack 'Type'}} \ + // expected-error{{Type' does not refer to the name of a parameter pack; did you mean 'Types'?}} +}; + diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp new file mode 100644 index 0000000..5c1029f --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -S -emit-llvm -std=c++11 -include %S/ser.h %s -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -emit-pch -o %t-ser.pch -std=c++11 -x c++ %S/ser.h +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -S -emit-llvm -std=c++11 -include-pch %t-ser.pch %s -o - | FileCheck %s + +struct D { + ~D() throw(); +}; +struct E { + ~E() throw(); +}; + +void test() { + bool b; + // CHECK: store i8 1 + b = noexcept(0); + // CHECK: store i8 0 + b = noexcept(throw 0); + b = f1(); + b = f2(); + + // CHECK-NOT: call void @_ZN1ED1Ev + // CHECK: call void @_ZN1DD1Ev + D(), noexcept(E()); +} +// CHECK: ret i1 true +// CHECK: ret i1 false diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp new file mode 100644 index 0000000..b5de1a7 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -0,0 +1,189 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -fms-extensions %s + +#define P(e) static_assert(noexcept(e), "expected nothrow") +#define N(e) static_assert(!noexcept(e), "expected throw") +#define B(b, e) static_assert(b == noexcept(e), "expectation failed") + +void simple() { + P(0); + P(0 + 0); + int i; + P(i); + P(sizeof(0)); + P(static_cast<int>(0)); + N(throw 0); + N((throw 0, 0)); +} + +void nospec(); +void allspec() throw(...); +void intspec() throw(int); +void emptyspec() throw(); +void nothrowattr() __attribute__((nothrow)); +void noexcept_true() noexcept; +void noexcept_false() noexcept(false); + +void call() { + N(nospec()); + N(allspec()); + N(intspec()); + P(emptyspec()); + P(nothrowattr()); + P(noexcept_true()); + N(noexcept_false()); +} + +void (*pnospec)(); +void (*pallspec)() throw(...); +void (*pintspec)() throw(int); +void (*pemptyspec)() throw(); + +void callptr() { + N(pnospec()); + N((*pnospec)()); + N(pallspec()); + N((*pallspec)()); + N(pintspec()); + N((*pintspec)()); + P(pemptyspec()); + P((*pemptyspec)()); +} + +struct S1 { + void nospec(); + void allspec() throw(...); + void intspec() throw(int); + void emptyspec() throw(); +}; + +void callmem() { + S1 s; + N(s.nospec()); + N(s.allspec()); + N(s.intspec()); + P(s.emptyspec()); +} + +void (S1::*mpnospec)(); +void (S1::*mpallspec)() throw(...); +void (S1::*mpintspec)() throw(int); +void (S1::*mpemptyspec)() throw(); + +void callmemptr() { + S1 s; + N((s.*mpnospec)()); + N((s.*mpallspec)()); + N((s.*mpintspec)()); + P((s.*mpemptyspec)()); +} + +struct S2 { + S2(); + S2(int, int) throw(); + void operator +(); + void operator -() throw(); + void operator +(int); + void operator -(int) throw(); + operator int(); + operator float() throw(); +}; + +void *operator new(__typeof__(sizeof(int)) sz, int) throw(); + +struct Bad1 { + ~Bad1() throw(int); +}; +struct Bad2 { + void operator delete(void*) throw(int); +}; + +typedef int X; + +void implicits() { + N(new int); + P(new (0) int); + P(delete (int*)0); + N(delete (Bad1*)0); + N(delete (Bad2*)0); + N(S2()); + P(S2(0, 0)); + S2 s; + N(+s); + P(-s); + N(s + 0); + P(s - 0); + N(static_cast<int>(s)); + P(static_cast<float>(s)); + N(Bad1()); + P(X().~X()); +} + +struct V { + virtual ~V() throw(); +}; +struct D : V {}; + +void dyncast() { + V *pv = 0; + D *pd = 0; + P(dynamic_cast<V&>(*pd)); + P(dynamic_cast<V*>(pd)); + N(dynamic_cast<D&>(*pv)); + P(dynamic_cast<D*>(pv)); +} + +namespace std { + struct type_info {}; +} + +void idtype() { + P(typeid(V)); + P(typeid((V*)0)); + P(typeid(*(S1*)0)); + N(typeid(*(V*)0)); +} + +void uneval() { + P(sizeof(typeid(*(V*)0))); + P(typeid(typeid(*(V*)0))); +} + +struct G1 {}; +struct G2 { int i; }; +struct G3 { S2 s; }; + +void gencon() { + P(G1()); + P(G2()); + N(G3()); +} + +template <class T> void f(T&&) noexcept; +template <typename T, bool b> +void late() { + B(b, typeid(*(T*)0)); + B(b, T(1)); + B(b, static_cast<T>(S2(0, 0))); + B(b, S1() + T()); + P(f(T())); + P(new (0) T); + P(delete (T*)0); +} +struct S3 { + virtual ~S3() throw(); + S3() throw(); + explicit S3(int); + S3(const S2&); +}; +template <class T> T&& f2() noexcept; +template <typename T> +void late2() { + P(dynamic_cast<S3&>(f2<T&>())); +} +void operator +(const S1&, float) throw(); +void operator +(const S1&, const S3&); +void tlate() { + late<float, true>(); + late<S3, false>(); + late2<S3>(); +} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h new file mode 100644 index 0000000..e6e7b79 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h @@ -0,0 +1,8 @@ +// Serialization testing helper for noexcept, included by cg.cpp. + +inline bool f1() { + return noexcept(0); +} +inline bool f2() { + return noexcept(throw 0); +} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp new file mode 100644 index 0000000..2dd6b23 --- /dev/null +++ b/clang/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; +} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp new file mode 100644 index 0000000..06cc610 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// rdar://problem/8347416 +namespace test0 { + struct A { + void foo(void (A::*)(int)); // expected-note {{passing argument to parameter here}} + template<typename T> void g(T); + + void test() { + foo(&g<int>); // expected-error {{can't form member pointer of type 'void (test0::A::*)(int)' without '&' and class name}} + } + }; +} + +// This should succeed. +namespace test1 { + struct A { + static void f(void (A::*)()); + static void f(void (*)(int)); + void g(); + static void g(int); + + void test() { + f(&g); + } + }; +} + +// Also rdar://problem/8347416 +namespace test2 { + struct A { + static int foo(short); + static int foo(float); + int foo(int); + int foo(double); + + void test(); + }; + + void A::test() { + int (A::*ptr)(int) = &(A::foo); // expected-error {{can't form member pointer of type 'int (test2::A::*)(int)' without '&' and class name}} + } +} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp new file mode 100644 index 0000000..ac11940 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// -- prvalue of arithmetic + +bool b = !0; + +bool b2 = !1.2; + +bool b3 = !4; + +// -- unscoped enumeration +enum { E, F }; + +bool b4 = !E; +bool b5 = !F; + +// -- pointer, +bool b6 = !&b4; +void f(); +bool b61 = !&f; + +// -- or pointer to member type can be converted to a prvalue of type bool. +struct S { void f() { } }; + +bool b7 = !&S::f; + + +bool b8 = !S(); //expected-error {{invalid argument type 'S'}} + +namespace PR8181 +{ + bool f() { } // expected-note{{possible target for call}} + void f(char) { } // expected-note{{possible target for call}} + bool b = !&f; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} +} diff --git a/clang/test/CXX/expr/p3.cpp b/clang/test/CXX/expr/p3.cpp new file mode 100644 index 0000000..6b243c2 --- /dev/null +++ b/clang/test/CXX/expr/p3.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +double operator +(double, double); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} + +struct A +{ + operator int(); +}; + +int main() +{ + A a, b; + int i0 = a + 1; + int i1 = a + b; +} diff --git a/clang/test/CXX/expr/p8.cpp b/clang/test/CXX/expr/p8.cpp new file mode 100644 index 0000000..2f6c094 --- /dev/null +++ b/clang/test/CXX/expr/p8.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int a0; +const volatile int a1 = 2; +int a2[16]; +int a3(); + +void f0(int); +void f1(int *); +void f2(int (*)()); + +int main() +{ + f0(a0); + f0(a1); + f1(a2); + f2(a3); +} diff --git a/clang/test/CXX/expr/p9.cpp b/clang/test/CXX/expr/p9.cpp new file mode 100644 index 0000000..803b0cc --- /dev/null +++ b/clang/test/CXX/expr/p9.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// floating-point overloads + +__typeof__(0 + 0.0L) ld0; +long double &ldr = ld0; + +__typeof__(0 + 0.0) d0; +double &dr = d0; + +__typeof__(0 + 0.0f) f0; +float &fr = f0; + +// integral promotions + +signed char c0; +__typeof__(c0 + c0) c1; +int &cr = c1; + +unsigned char uc0; +__typeof__(uc0 + uc0) uc1; +int &ucr = uc1; + +short s0; +__typeof__(s0 + s0) s1; +int &sr = s1; + +unsigned short us0; +__typeof__(us0 + us0) us1; +int &usr = us1; + +// integral overloads + +__typeof__(0 + 0UL) ul0; +unsigned long &ulr = ul0; + +template<bool T> struct selector; +template<> struct selector<true> { typedef long type; }; +template<> struct selector<false> {typedef unsigned long type; }; +__typeof__(0U + 0L) ui_l0; +selector<(sizeof(long) > sizeof(unsigned int))>::type &ui_lr = ui_l0; + +__typeof__(0 + 0L) l0; +long &lr = l0; + +__typeof__(0 + 0U) u0; +unsigned &ur = u0; + +__typeof__(0 + 0) i0; +int &ir = i0; |