diff options
Diffstat (limited to 'test/SemaCXX')
110 files changed, 5769 insertions, 0 deletions
diff --git a/test/SemaCXX/__null.cpp b/test/SemaCXX/__null.cpp new file mode 100644 index 0000000..4672801 --- /dev/null +++ b/test/SemaCXX/__null.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify && +// RUN: clang-cc -triple i686-unknown-unknown %s -fsyntax-only -verify + +void f() { + int* i = __null; + i = __null; + int i2 = __null; + + // Verify statically that __null is the right size + int a[sizeof(typeof(__null)) == sizeof(void*)? 1 : -1]; + + // Verify that null is evaluated as 0. + int b[__null ? -1 : 1]; +} diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp new file mode 100644 index 0000000..dc764da --- /dev/null +++ b/test/SemaCXX/abstract.cpp @@ -0,0 +1,128 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) +#define __CONCAT1(__X, __Y) __X ## __Y + +#define static_assert(__b, __m) \ + typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1] +#endif + +class C { + virtual void f() = 0; // expected-note {{pure virtual function 'f'}} +}; + +static_assert(__is_abstract(C), "C has a pure virtual function"); + +class D : C { +}; + +static_assert(__is_abstract(D), "D inherits from an abstract class"); + +class E : D { + virtual void f(); +}; + +static_assert(!__is_abstract(E), "E inherits from an abstract class but implements f"); + +C *d = new C; // expected-error {{allocation of an object of abstract type 'C'}} + +C c; // expected-error {{variable type 'C' is an abstract class}} +void t1(C c); // expected-error {{parameter type 'C' is an abstract class}} +void t2(C); // expected-error {{parameter type 'C' is an abstract class}} + +struct S { + C c; // expected-error {{field type 'C' is an abstract class}} +}; + +void t3(const C&); + +void f() { + C(); // expected-error {{allocation of an object of abstract type 'C'}} + t3(C()); // expected-error {{allocation of an object of abstract type 'C'}} +} + +C e1[2]; // expected-error {{variable type 'C' is an abstract class}} +C (*e2)[2]; // expected-error {{variable type 'C' is an abstract class}} +C (**e3)[2]; // expected-error {{variable type 'C' is an abstract class}} + +void t4(C c[2]); // expected-error {{parameter type 'C' is an abstract class}} + +void t5(void (*)(C)); // expected-error {{parameter type 'C' is an abstract class}} + +typedef void (*Func)(C); // expected-error {{parameter type 'C' is an abstract class}} +void t6(Func); + +class F { + F a() { } // expected-error {{return type 'F' is an abstract class}} + + class D { + void f(F c); // expected-error {{parameter type 'F' is an abstract class}} + }; + + union U { + void u(F c); // expected-error {{parameter type 'F' is an abstract class}} + }; + + virtual void f() = 0; // expected-note {{pure virtual function 'f'}} +}; + +class Abstract; + +void t7(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}} + +void t8() { + void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}} +} + +namespace N { + void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}} +} + +class Abstract { + virtual void f() = 0; // expected-note {{pure virtual function 'f'}} +}; + +// <rdar://problem/6854087> +class foo { +public: + virtual foo *getFoo() = 0; +}; + +class bar : public foo { +public: + virtual bar *getFoo(); +}; + +bar x; + +// <rdar://problem/6902298> +class A +{ +public: + virtual void release() = 0; + virtual void release(int count) = 0; + virtual void retain() = 0; +}; + +class B : public A +{ +public: + virtual void release(); + virtual void release(int count); + virtual void retain(); +}; + +void foo(void) +{ + B b; +} + +struct K { + int f; + virtual ~K(); +}; + +struct L : public K { + void f(); +}; diff --git a/test/SemaCXX/access-base-class.cpp b/test/SemaCXX/access-base-class.cpp new file mode 100644 index 0000000..4a9ee51 --- /dev/null +++ b/test/SemaCXX/access-base-class.cpp @@ -0,0 +1,82 @@ +// RUN: clang-cc -fsyntax-only -faccess-control -verify %s +namespace T1 { + +class A { }; +class B : private A { }; // expected-note {{'private' inheritance specifier here}} + +void f(B* b) { + A *a = b; // expected-error{{conversion from 'class T1::B' to inaccessible base class 'class T1::A'}} \ + expected-error{{incompatible type initializing 'class T1::B *', expected 'class T1::A *'}} +} + +} + +namespace T2 { + +class A { }; +class B : A { }; // expected-note {{inheritance is implicitly 'private'}} + +void f(B* b) { + A *a = b; // expected-error {{conversion from 'class T2::B' to inaccessible base class 'class T2::A'}} \ + expected-error {{incompatible type initializing 'class T2::B *', expected 'class T2::A *'}} +} + +} + +namespace T3 { + +class A { }; +class B : public A { }; + +void f(B* b) { + A *a = b; +} + +} + +namespace T4 { + +class A {}; + +class B : private virtual A {}; +class C : public virtual A {}; + +class D : public B, public C {}; + +void f(D *d) { + // This takes the D->C->B->A path. + A *a = d; +} + +} + +namespace T5 { + class A {}; + + class B : private A { + void f(B *b) { + A *a = b; + } + }; +} + +namespace T6 { + class C; + + class A {}; + + class B : private A { // expected-note {{'private' inheritance specifier here}} + void f(C* c); + }; + + class C : public B { + void f(C *c) { + A* a = c; // expected-error {{conversion from 'class T6::C' to inaccessible base class 'class T6::A'}} \ + expected-error {{incompatible type initializing 'class T6::C *', expected 'class T6::A *'}} + } + }; + + void B::f(C *c) { + A *a = c; + } +} diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp new file mode 100644 index 0000000..cfbc9c8 --- /dev/null +++ b/test/SemaCXX/access.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class C { + struct S; // expected-note {{previously declared 'private' here}} +public: + + struct S {}; // expected-error {{'S' redeclared with 'public' access}} +}; + +struct S { + class C; // expected-note {{previously declared 'public' here}} + +private: + class C { }; // expected-error {{'C' redeclared with 'private' access}} +}; + +class T { +protected: + template<typename T> struct A; // expected-note {{previously declared 'protected' here}} + +private: + template<typename T> struct A {}; // expected-error {{'A' redeclared with 'private' access}} +}; diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp new file mode 100644 index 0000000..9c9f0e1 --- /dev/null +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int f(double); +int f(int); + +int (*pfd)(double) = f; // selects f(double) +int (*pfd2)(double) = &f; // selects f(double) +int (*pfd3)(double) = ((&((f)))); // selects f(double) +int (*pfi)(int) = &f; // selects f(int) +// FIXME: This error message is not very good. We need to keep better +// track of what went wrong when the implicit conversion failed to +// give a better error message here. +int (*pfe)(...) = &f; // expected-error{{incompatible type initializing '<overloaded function type>', expected 'int (*)(...)'}} +int (&rfi)(int) = f; // selects f(int) +int (&rfd)(double) = f; // selects f(double) + +void g(int (*fp)(int)); // expected-note{{note: candidate function}} +void g(int (*fp)(float)); +void g(int (*fp)(double)); // expected-note{{note: candidate function}} + +int g1(int); +int g1(char); + +int g2(int); +int g2(double); + +void g_test() { + g(g1); + g(g2); // expected-error{{call to 'g' is ambiguous; candidates are:}} +} diff --git a/test/SemaCXX/address-of.cpp b/test/SemaCXX/address-of.cpp new file mode 100644 index 0000000..4e436d6 --- /dev/null +++ b/test/SemaCXX/address-of.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR clang/3175 + +void bar(int*); + +class c { + int var; + static int svar; + void foo() { + bar(&var); + bar(&svar); + } + + static void wibble() { + bar(&var); // expected-error{{invalid use of member 'var' in static member function}} + bar(&svar); + } +}; + +enum E { + Enumerator +}; + +void test() { + (void)&Enumerator; // expected-error{{address expression must be an lvalue or a function designator}} +} + +template<int N> +void test2() { + (void)&N; // expected-error{{address expression must be an lvalue or a function designator}} +} + +// PR clang/3222 +void xpto(); +void (*xyz)(void) = &xpto; diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp new file mode 100644 index 0000000..c96eda4 --- /dev/null +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 %s + +// Verify that we can't initialize non-aggregates with an initializer +// list. +struct NonAggr1 { + NonAggr1(int) { } + + int m; +}; + +struct Base { }; +struct NonAggr2 : public Base { + int m; +}; + +class NonAggr3 { + int m; +}; + +struct NonAggr4 { + int m; + virtual void f(); +}; + +NonAggr1 na1 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr1' with an initializer list}} +NonAggr2 na2 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr2' with an initializer list}} +NonAggr3 na3 = { 17 }; // expected-error{{initialization of non-aggregate type 'class NonAggr3' with an initializer list}} +NonAggr4 na4 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr4' with an initializer list}} diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp new file mode 100644 index 0000000..f77fa03 --- /dev/null +++ b/test/SemaCXX/anonymous-union.cpp @@ -0,0 +1,113 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + union { + float f3; + double d2; + } named; + + union { + int i; + float f; + + union { + float f2; + mutable double d; + }; + }; + + void test_unqual_references(); + + struct { + int a; + float b; + }; + + void test_unqual_references_const() const; + + mutable union { // expected-error{{anonymous union at class scope must not have a storage specifier}} + float c1; + double c2; + }; +}; + +void X::test_unqual_references() { + i = 0; + f = 0.0; + f2 = f; + d = f; + f3 = 0; // expected-error{{use of undeclared identifier 'f3'}} + a = 0; +} + +void X::test_unqual_references_const() const { + d = 0.0; + f2 = 0; // expected-error{{read-only variable is not assignable}} + a = 0; // expected-error{{read-only variable is not assignable}} +} + +void test_unqual_references(X x, const X xc) { + x.i = 0; + x.f = 0.0; + x.f2 = x.f; + x.d = x.f; + x.f3 = 0; // expected-error{{no member named 'f3'}} + x.a = 0; + + xc.d = 0.0; + xc.f = 0; // expected-error{{read-only variable is not assignable}} + xc.a = 0; // expected-error{{read-only variable is not assignable}} +} + + +struct Redecl { + int x; // expected-note{{previous declaration is here}} + class y { }; + + union { + int x; // expected-error{{member of anonymous union redeclares 'x'}} + float y; + double z; // expected-note{{previous declaration is here}} + double zz; // expected-note{{previous definition is here}} + }; + + int z; // expected-error{{duplicate member 'z'}} + void zz(); // expected-error{{redefinition of 'zz' as different kind of symbol}} +}; + +union { // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} + int int_val; + float float_val; +}; + +static union { + int int_val2; + float float_val2; +}; + +void f() { + int_val2 = 0; + float_val2 = 0.0; +} + +void g() { + union { + int i; + float f2; + }; + i = 0; + f2 = 0.0; +} + +struct BadMembers { + union { + struct X { }; // expected-error {{types cannot be declared in an anonymous union}} + struct { int x; int y; } y; + + void f(); // expected-error{{functions cannot be declared in an anonymous union}} + private: int x1; // expected-error{{anonymous union cannot contain a private data member}} + protected: float x2; // expected-error{{anonymous union cannot contain a protected data member}} + }; +}; + +// <rdar://problem/6481130> +typedef union { }; // expected-error{{declaration does not declare anything}} diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp new file mode 100644 index 0000000..8e5f76b --- /dev/null +++ b/test/SemaCXX/attr-unavailable.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int &foo(int); +double &foo(double); +void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ +// expected-note{{function has been explicitly marked unavailable here}} + +void bar(...) __attribute__((__unavailable__)); // expected-note 2{{explicitly marked unavailable}} + +void test_foo(short* sp) { + int &ir = foo(1); + double &dr = foo(1.0); + foo(sp); // expected-error{{call to unavailable function 'foo'}} + + void (*fp)(...) = &bar; // expected-warning{{'bar' is unavailable}} + void (*fp2)(...) = bar; // expected-warning{{'bar' is unavailable}} + + int &(*fp3)(int) = foo; + void (*fp4)(...) = foo; // expected-warning{{'foo' is unavailable}} +} diff --git a/test/SemaCXX/basic_lookup_argdep.cpp b/test/SemaCXX/basic_lookup_argdep.cpp new file mode 100644 index 0000000..486a688 --- /dev/null +++ b/test/SemaCXX/basic_lookup_argdep.cpp @@ -0,0 +1,60 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { + struct X { }; + + X operator+(X, X); + + void f(X); + void g(X); // expected-note{{candidate function}} + + void test_multiadd(X x) { + (void)(x + x); + } +} + +namespace M { + struct Y : N::X { }; +} + +void f(); + +void test_operator_adl(N::X x, M::Y y) { + (void)(x + x); + (void)(y + y); +} + +void test_func_adl(N::X x, M::Y y) { + f(x); + f(y); + (f)(x); // expected-error{{too many arguments to function call}} + ::f(x); // expected-error{{too many arguments to function call}} +} + +namespace N { + void test_multiadd2(X x) { + (void)(x + x); + } +} + + +void test_func_adl_only(N::X x) { + g(x); +} + +namespace M { + int g(N::X); // expected-note{{candidate function}} + + void test(N::X x) { + g(x); // expected-error{{call to 'g' is ambiguous; candidates are:}} + int i = (g)(x); + + int g(N::X); + g(x); // okay; calls locally-declared function, no ADL + } +} + + +void test_operator_name_adl(N::X x) { + (void)operator+(x, x); +} diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp new file mode 100644 index 0000000..9d789bb --- /dev/null +++ b/test/SemaCXX/blocks.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks + +void tovoid(void*); + +void tovoid_test(int (^f)(int, int)) { + tovoid(f); +} + +void reference_lvalue_test(int& (^f)()) { + f() = 10; +} diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp new file mode 100644 index 0000000..bc44c73 --- /dev/null +++ b/test/SemaCXX/bool.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Bool literals can be enum values. +enum { + ReadWrite = false, + ReadOnly = true +}; + +// bool cannot be decremented, and gives a warning on increment +void test(bool b) +{ + ++b; // expected-warning {{incrementing expression of type bool is deprecated}} + b++; // expected-warning {{incrementing expression of type bool is deprecated}} + --b; // expected-error {{cannot decrement expression of type bool}} + b--; // expected-error {{cannot decrement expression of type bool}} + + bool *b1 = (int *)0; // expected-error{{expected 'bool *'}} +} diff --git a/test/SemaCXX/carbon.cpp b/test/SemaCXX/carbon.cpp new file mode 100644 index 0000000..0e7570f --- /dev/null +++ b/test/SemaCXX/carbon.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -mcpu=pentium4 %s -fsyntax-only -print-stats +#ifdef __APPLE__ +#include <Carbon/Carbon.h> +#endif + diff --git a/test/SemaCXX/class-names.cpp b/test/SemaCXX/class-names.cpp new file mode 100644 index 0000000..a5569c0 --- /dev/null +++ b/test/SemaCXX/class-names.cpp @@ -0,0 +1,52 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class C { }; + +C c; + +void D(int); + +class D {}; // expected-note {{previous use is here}} + +void foo() +{ + D(5); + class D d; +} + +class D; + +enum D; // expected-error {{use of 'D' with tag type that does not match previous declaration}} + +class A * A; + +class A * a2; + +void bar() +{ + A = 0; +} + +void C(int); + +void bar2() +{ + C(17); +} + +extern int B; +class B; +class B {}; +int B; + +enum E { e1_val }; +E e1; + +void E(int); + +void bar3() { + E(17); +} + +enum E e2; + +enum E2 { E2 }; diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp new file mode 100644 index 0000000..d2a8114 --- /dev/null +++ b/test/SemaCXX/class.cpp @@ -0,0 +1,112 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class C { +public: + auto int errx; // expected-error {{error: storage class specified for a member declaration}} + register int erry; // expected-error {{error: storage class specified for a member declaration}} + extern int errz; // expected-error {{error: storage class specified for a member declaration}} + + static void sm() { + sx = 0; + this->x = 0; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} + x = 0; // expected-error {{error: invalid use of member 'x' in static member function}} + } + + class NestedC { + void m() { + sx = 0; + x = 0; // expected-error {{error: invalid use of nonstatic data member 'x'}} + } + }; + + int b : 1, w : 2; + int : 1, : 2; + typedef int E : 1; // expected-error {{typedef member 'E' cannot be a bit-field}} + static int sb : 1; // expected-error {{error: static member 'sb' cannot be a bit-field}} + static int vs; + + typedef int func(); + func tm; + func *ptm; + func btm : 1; // expected-error {{bit-field 'btm' has non-integral type}} + NestedC bc : 1; // expected-error {{bit-field 'bc' has non-integral type}} + + enum E1 { en1, en2 }; + + int i = 0; // expected-error {{error: 'i' can only be initialized if it is a static const integral data member}} + static int si = 0; // expected-error {{error: 'si' can only be initialized if it is a static const integral data member}} + static const NestedC ci = 0; // expected-error {{error: 'ci' can only be initialized if it is a static const integral data member}} + static const int nci = vs; // expected-error {{in-class initializer is not an integral constant expression}} + static const int vi = 0; + static const E evi = 0; + + void m() { + sx = 0; + this->x = 0; + y = 0; + this = 0; // expected-error {{error: expression is not assignable}} + } + + int f1(int p) { + A z = 6; + return p + x + this->y + z; + } + + typedef int A; + + virtual int viv; // expected-error {{'virtual' can only appear on non-static member functions}} + virtual static int vsif(); // expected-error {{error: 'virtual' can only appear on non-static member functions}} + virtual int vif(); + +private: + int x,y; + static int sx; + + mutable int mi; + mutable int &mir; // expected-error {{error: 'mutable' cannot be applied to references}} + mutable void mfn(); // expected-error {{error: 'mutable' cannot be applied to functions}} + mutable const int mci; // expected-error {{error: 'mutable' and 'const' cannot be mixed}} + + static const int number = 50; + static int arr[number]; +}; + +class C2 { + void f() { + static int lx; + class LC1 { + int m() { return lx; } + }; + class LC2 { + int m() { return lx; } + }; + } +}; + +struct C3 { + int i; + mutable int j; +}; +void f() +{ + const C3 c3 = { 1, 2 }; + (void)static_cast<int*>(&c3.i); // expected-error {{static_cast from 'int const *' to 'int *' is not allowed}} + // but no error here + (void)static_cast<int*>(&c3.j); +} + +// Play with mutable a bit more, to make sure it doesn't crash anything. +mutable int gi; // expected-error {{error: 'mutable' can only be applied to member variables}} +mutable void gfn(); // expected-error {{illegal storage class on function}} +void ogfn() +{ + mutable int ml; // expected-error {{error: 'mutable' can only be applied to member variables}} + + // PR3020: This used to crash due to double ownership of C4. + struct C4; + C4; // expected-error {{declaration does not declare anything}} +} + +struct C4 { + void f(); // expected-note{{previous declaration is here}} + int f; // expected-error{{duplicate member 'f'}} +}; diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp new file mode 100644 index 0000000..55d3c76 --- /dev/null +++ b/test/SemaCXX/complex-overload.cpp @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s +char *foo(float); // expected-note 3 {{candidate function}} + +void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); + // Note: GCC and EDG reject these two, but they are valid C99 conversions + char *cp3 = foo(fc); + char *cp4 = foo(dc); +} + +int *foo(float _Complex); // expected-note 3 {{candidate function}} + +void test_foo_2(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *ip = foo(fc); + int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}} +} + +long *foo(double _Complex); // expected-note {{candidate function}} + +void test_foo_3(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *ip = foo(fc); + long *lp = foo(dc); +} + +char *promote_or_convert(double _Complex); // expected-note{{candidate function}} +int *promote_or_convert(long double _Complex); // expected-note{{candidate function}} + +void test_promote_or_convert(float f, float _Complex fc) { + char *cp = promote_or_convert(fc); + int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}} +} + +char *promote_or_convert2(float); +int *promote_or_convert2(double _Complex); + +void test_promote_or_convert2(float _Complex fc) { + int *cp = promote_or_convert2(fc); +} + +char *promote_or_convert3(int _Complex); +int *promote_or_convert3(long _Complex); + +void test_promote_or_convert3(short _Complex sc) { + char *cp = promote_or_convert3(sc); +} diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp new file mode 100644 index 0000000..b4a5c88 --- /dev/null +++ b/test/SemaCXX/composite-pointer-type.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class Base { }; +class Derived1 : public Base { }; +class Derived2 : public Base { }; + +void f0(volatile Base *b, Derived1 *d1, const Derived2 *d2) { + if (b > d1) + return; + if (d1 <= b) + return; + if (b > d2) + return; + if (d1 >= d2) // expected-error{{comparison of distinct}} + return; +} + +void f1(volatile Base *b, Derived1 *d1, const Derived2 *d2) { + if (b == d1) + return; + if (d1 == b) + return; + if (b != d2) + return; + if (d1 == d2) // expected-error{{comparison of distinct}} + return; +} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp new file mode 100644 index 0000000..7c9cee5 --- /dev/null +++ b/test/SemaCXX/condition.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void test() { + int x; + if (x) ++x; + if (int x=0) ++x; + + typedef int arr[10]; + while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{initialization with '{...}' expected for array}} + while (int f()=0) ; // expected-error {{a function type is not allowed here}} + + struct S {} s; + if (s) ++x; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + while (struct S x=s) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + do ; while (s); // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + for (;s;) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}} + + while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{value of type 'struct <anonymous>' is not contextually convertible to 'bool'}} + switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}} + + if (int x=0) { // expected-note 2 {{previous definition is here}} + int x; // expected-error {{redefinition of 'x'}} + } + else + int x; // expected-error {{redefinition of 'x'}} + while (int x=0) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + while (int x=0) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (int x; int x=0; ) ; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (int x; ; ) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (; int x=0; ) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (; int x=0; ) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + switch (int x=0) { default: int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +} diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp new file mode 100644 index 0000000..3f4d715 --- /dev/null +++ b/test/SemaCXX/conditional-expr.cpp @@ -0,0 +1,181 @@ +// RUN: clang-cc -fsyntax-only -verify -faccess-control -std=c++0x %s + +// C++ rules for ?: are a lot stricter than C rules, and have to take into +// account more conversion options. +// This test runs in C++0x mode for the contextual conversion of the condition. + +struct ToBool { explicit operator bool(); }; + +struct B; +struct A { A(); A(const B&); }; +struct B { operator A() const; }; +struct I { operator int(); }; +struct J { operator I(); }; +struct K { operator double(); }; +typedef void (*vfn)(); +struct F { operator vfn(); }; +struct G { operator vfn(); }; + +struct Base { + int trick(); + A trick() const; + void fn1(); +}; +struct Derived : Base { + void fn2(); +}; +struct Convertible { operator Base&(); }; +struct Priv : private Base {}; // expected-note 2 {{'private' inheritance specifier here}} +struct Mid : Base {}; +struct Fin : Mid, Derived {}; +typedef void (Derived::*DFnPtr)(); +struct ToMemPtr { operator DFnPtr(); }; + +struct BadDerived; +struct BadBase { operator BadDerived&(); }; +struct BadDerived : BadBase {}; + +struct Fields { + int i1, i2, b1 : 3, b2 : 3; +}; +struct MixedFields { + int i; + volatile int vi; + const int ci; + const volatile int cvi; +}; +struct MixedFieldsDerived : MixedFields { +}; + +enum Enum { EVal }; + +struct Ambig { + operator short(); + operator signed char(); +}; + +void test() +{ + // This function tests C++0x 5.16 + + // p1 (contextually convert to bool) + int i1 = ToBool() ? 0 : 1; + + // p2 (one or both void, and throwing) + i1 ? throw 0 : throw 1; + i1 ? test() : throw 1; + i1 ? throw 0 : test(); + i1 ? test() : test(); + i1 = i1 ? throw 0 : 0; + i1 = i1 ? 0 : throw 0; + i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}} + i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}} + (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}} + (i1 ? i1 : throw 0) = 0; // expected-error {{expression is not assignable}} + + // p3 (one or both class type, convert to each other) + // b1 (lvalues) + Base base; + Derived derived; + Convertible conv; + Base &bar1 = i1 ? base : derived; + Base &bar2 = i1 ? derived : base; + Base &bar3 = i1 ? base : conv; + Base &bar4 = i1 ? conv : base; + // these are ambiguous + BadBase bb; + BadDerived bd; + (void)(i1 ? bb : bd); // expected-error {{conditional expression is ambiguous; 'struct BadBase' can be converted to 'struct BadDerived' and vice versa}} + (void)(i1 ? bd : bb); // expected-error {{conditional expression is ambiguous}} + // curiously enough (and a defect?), these are not + // for rvalues, hierarchy takes precedence over other conversions + (void)(i1 ? BadBase() : BadDerived()); + (void)(i1 ? BadDerived() : BadBase()); + + // b2.1 (hierarchy stuff) + const Base constret(); + const Derived constder(); + // should use const overload + A a1((i1 ? constret() : Base()).trick()); + A a2((i1 ? Base() : constret()).trick()); + A a3((i1 ? constret() : Derived()).trick()); + A a4((i1 ? Derived() : constret()).trick()); + // should use non-const overload + i1 = (i1 ? Base() : Base()).trick(); + i1 = (i1 ? Base() : Base()).trick(); + i1 = (i1 ? Base() : Derived()).trick(); + i1 = (i1 ? Derived() : Base()).trick(); + // should fail: const lost + (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('struct Base' and 'struct Derived const')}} + (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('struct Derived const' and 'struct Base')}} + + // FIXME: these are invalid hierarchy conversions + Priv priv; + Fin fin; + (void)(i1 ? Base() : Priv()); // xpected-error private base + (void)(i1 ? Priv() : Base()); // xpected-error private base + (void)(i1 ? Base() : Fin()); // xpected-error ambiguous base + (void)(i1 ? Fin() : Base()); // xpected-error ambiguous base + (void)(i1 ? base : priv); // expected-error {{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} + (void)(i1 ? priv : base); // expected-error {{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} + (void)(i1 ? base : fin); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + (void)(i1 ? fin : base); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + + // b2.2 (non-hierarchy) + i1 = i1 ? I() : i1; + i1 = i1 ? i1 : I(); + I i2(i1 ? I() : J()); + I i3(i1 ? J() : I()); + // "the type [it] woud have if E2 were converted to an rvalue" + vfn pfn = i1 ? F() : test; + pfn = i1 ? test : F(); + // these are ambiguous - better messages would be nice + (void)(i1 ? A() : B()); // expected-error {{incompatible operand types}} + (void)(i1 ? B() : A()); // expected-error {{incompatible operand types}} + (void)(i1 ? 1 : Ambig()); // expected-error {{incompatible operand types}} + (void)(i1 ? Ambig() : 1); // expected-error {{incompatible operand types}} + // By the way, this isn't an lvalue: + &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}} + + // p4 (lvalue, same type) + Fields flds; + int &ir1 = i1 ? flds.i1 : flds.i2; + (i1 ? flds.b1 : flds.i2) = 0; + (i1 ? flds.i1 : flds.b2) = 0; + (i1 ? flds.b1 : flds.b2) = 0; + + // p5 (conversion to built-in types) + // GCC 4.3 fails these + double d1 = i1 ? I() : K(); + pfn = i1 ? F() : G(); + DFnPtr pfm; + pfm = i1 ? DFnPtr() : &Base::fn1; + pfm = i1 ? &Base::fn1 : DFnPtr(); + + // p6 (final conversions) + i1 = i1 ? i1 : ir1; + int *pi1 = i1 ? &i1 : 0; + pi1 = i1 ? 0 : &i1; + i1 = i1 ? i1 : EVal; + i1 = i1 ? EVal : i1; + d1 = i1 ? 'c' : 4.0; + d1 = i1 ? 4.0 : 'c'; + Base *pb = i1 ? (Base*)0 : (Derived*)0; + pb = i1 ? (Derived*)0 : (Base*)0; + pfm = i1 ? &Base::fn1 : &Derived::fn2; + pfm = i1 ? &Derived::fn2 : &Base::fn1; + pfm = i1 ? &Derived::fn2 : 0; + pfm = i1 ? 0 : &Derived::fn2; + const int (MixedFieldsDerived::*mp1) = + i1 ? &MixedFields::ci : &MixedFieldsDerived::i; + const volatile int (MixedFields::*mp2) = + i1 ? &MixedFields::ci : &MixedFields::cvi; + i1 ? &MixedFields::ci : &MixedFields::vi; // expected-error {{incompatible operand types}} + // Conversion of primitives does not result in an lvalue. + &(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}} + + + // Note the thing that this does not test: since DR446, various situations + // *must* create a separate temporary copy of class objects. This can only + // be properly tested at runtime, though. +} diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp new file mode 100644 index 0000000..39d61db --- /dev/null +++ b/test/SemaCXX/const-cast.cpp @@ -0,0 +1,63 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; + +// See if aliasing can confuse this baby. +typedef char c; +typedef c *cp; +typedef cp *cpp; +typedef cpp *cppp; +typedef cppp &cpppr; +typedef const cppp &cpppcr; +typedef const char cc; +typedef cc *ccp; +typedef volatile ccp ccvp; +typedef ccvp *ccvpp; +typedef const volatile ccvpp ccvpcvp; +typedef ccvpcvp *ccvpcvpp; +typedef int iar[100]; +typedef iar &iarr; +typedef int (*f)(int); + +char ***good_const_cast_test(ccvpcvpp var) +{ + // Cast away deep consts and volatiles. + char ***var2 = const_cast<cppp>(var); + char ***const &var3 = var2; + // Const reference to reference. + char ***&var4 = const_cast<cpppr>(var3); + // Drop reference. Intentionally without qualifier change. + char *** var5 = const_cast<cppp>(var4); + const int ar[100] = {0}; + int (&rar)[100] = const_cast<iarr>(ar); // expected-error {{const_cast from 'int const [100]' to 'iarr' (aka 'iar &') is not allowed}} + // Array decay. Intentionally without qualifier change. + int *pi = const_cast<int*>(ar); + f fp = 0; + // Don't misidentify fn** as a function pointer. + f *fpp = const_cast<f*>(&fp); + int const A::* const A::*icapcap = 0; + int A::* A::* iapap = const_cast<int A::* A::*>(icapcap); + + return var4; +} + +short *bad_const_cast_test(char const *volatile *const volatile *var) +{ + // Different pointer levels. + char **var2 = const_cast<char**>(var); // expected-error {{const_cast from 'char const *volatile *const volatile *' to 'char **' is not allowed}} + // Different final type. + short ***var3 = const_cast<short***>(var); // expected-error {{const_cast from 'char const *volatile *const volatile *' to 'short ***' is not allowed}} + // Rvalue to reference. + char ***&var4 = const_cast<cpppr>(&var2); // expected-error {{const_cast from rvalue to reference type 'cpppr'}} + // Non-pointer. + char v = const_cast<char>(**var2); // expected-error {{const_cast to 'char', which is not a reference, pointer-to-object, or pointer-to-data-member}} + const int *ar[100] = {0}; + // Not even lenient g++ accepts this. + int *(*rar)[100] = const_cast<int *(*)[100]>(&ar); // expected-error {{const_cast from 'int const *(*)[100]' to 'int *(*)[100]' is not allowed}} + f fp1 = 0; + // Function pointers. + f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} + void (A::*mfn)() = 0; + (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (struct A::*)(void)', which is not a reference, pointer-to-object, or pointer-to-data-member}} + return **var3; +} diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp new file mode 100644 index 0000000..02ea802 --- /dev/null +++ b/test/SemaCXX/constant-expression.cpp @@ -0,0 +1,83 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 %s + +// C++ [expr.const]p1: +// In several places, C++ requires expressions that evaluate to an integral +// or enumeration constant: as array bounds, as case expressions, as +// bit-field lengths, as enumerator initializers, as static member +// initializers, and as integral or enumeration non-type template arguments. +// An integral constant-expression can involve only literals, enumerators, +// const variables or static data members of integral or enumeration types +// initialized with constant expressions, and sizeof expressions. Floating +// literals can appear only if they are cast to integral or enumeration types. + +enum Enum { eval = 1 }; +const int cval = 2; +const Enum ceval = eval; +struct Struct { + static const int sval = 3; + static const Enum seval = eval; +}; + +template <int itval, Enum etval> struct C { + enum E { + v1 = 1, + v2 = eval, + v3 = cval, + v4 = ceval, + v5 = Struct::sval, + v6 = Struct::seval, + v7 = itval, + v8 = etval, + v9 = (int)1.5, + v10 = sizeof(Struct), + v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + }; + unsigned + b1 : 1, + b2 : eval, + b3 : cval, + b4 : ceval, + b5 : Struct::sval, + b6 : Struct::seval, + b7 : itval, + b8 : etval, + b9 : (int)1.5, + b10 : sizeof(Struct), + b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + ; + static const int + i1 = 1, + i2 = eval, + i3 = cval, + i4 = ceval, + i5 = Struct::sval, + i6 = Struct::seval, + i7 = itval, + i8 = etval, + i9 = (int)1.5, + i10 = sizeof(Struct), + i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + ; + void f() { + switch(0) { + case 0 + 1: + case 100 + eval: + case 200 + cval: + case 300 + ceval: + case 400 + Struct::sval: + case 500 + Struct::seval: + case 600 + itval: + case 700 + etval: + case 800 + (int)1.5: + case 900 + sizeof(Struct): + case 1000 + (true? 1 + cval * Struct::sval ^ + itval / (int)1.5 - sizeof(Struct) : 0): + ; + } + } + typedef C<itval, etval> T0; +}; + +template struct C<1, eval>; +//template struct C<cval, ceval>; +//template struct C<Struct::sval, Struct::seval>; diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp new file mode 100644 index 0000000..d0c978a --- /dev/null +++ b/test/SemaCXX/constructor-initializer.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { + int m; +}; + +class B : public A { +public: + B() : A(), m(1), n(3.14) { } + +private: + int m; + float n; +}; + + +class C : public virtual B { +public: + C() : B() { } +}; + +class D : public C { +public: + D() : B(), C() { } +}; + +class E : public D, public B { +public: + E() : B(), D() { } // expected-error{{base class initializer 'B' names both a direct base class and an inherited virtual base class}} +}; + + +typedef int INT; + +class F : public B { +public: + int B; + + F() : B(17), + m(17), // expected-error{{member initializer 'm' does not name a non-static data member or base class}} + INT(17) // expected-error{{constructor initializer 'INT' (aka 'int') does not name a class}} + { + } +}; + +class G : A { + G() : A(10); // expected-error{{expected '{'}} +}; + +void f() : a(242) { } // expected-error{{only constructors take base initializers}} + +class H : A { + H(); +}; + +H::H() : A(10) { } + diff --git a/test/SemaCXX/constructor-recovery.cpp b/test/SemaCXX/constructor-recovery.cpp new file mode 100644 index 0000000..50fdc96 --- /dev/null +++ b/test/SemaCXX/constructor-recovery.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct C { // expected-note {{candidate function}} + virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}} \ + expected-note {{candidate function}} +}; + +void f() { + C c; // expected-error {{call to constructor of 'c' is ambiguous}} +} diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp new file mode 100644 index 0000000..8f289a2 --- /dev/null +++ b/test/SemaCXX/constructor.cpp @@ -0,0 +1,60 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef int INT; + +class Foo { + Foo(); + (Foo)(float) { } + explicit Foo(int); // expected-note {{previous declaration is here}} + Foo(const Foo&); + + ((Foo))(INT); // expected-error{{cannot be redeclared}} + + Foo(Foo foo, int i = 17, int j = 42); // expected-error{{copy constructor must pass its first argument by reference}} + + static Foo(short, short); // expected-error{{constructor cannot be declared 'static'}} + virtual Foo(double); // expected-error{{constructor cannot be declared 'virtual'}} + Foo(long) const; // expected-error{{'const' qualifier is not allowed on a constructor}} + + int Foo(int, int); // expected-error{{constructor cannot have a return type}} +}; + +Foo::Foo(const Foo&) { } + +typedef struct { + int version; +} Anon; +extern const Anon anon; +extern "C" const Anon anon2; + +// PR3188: The extern declaration complained about not having an appropriate +// constructor. +struct x; +extern x a; + +// A similar case. +struct y { + y(int); +}; +extern y b; + +struct Length { + Length l() const { return *this; } +}; + +// <rdar://problem/6815988> +struct mmst_reg{ + char mmst_reg[10]; +}; + +// PR3948 +namespace PR3948 { +// PR3948 +class a { + public: + int b(int a()); +}; +int x(); +void y() { + a z; z.b(x); +} +} diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp new file mode 100644 index 0000000..1ca1e68 --- /dev/null +++ b/test/SemaCXX/conversion-function.cpp @@ -0,0 +1,66 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { +public: + operator bool(); + operator int() const; + + bool f() { + return operator bool(); + } + + float g() { + return operator float(); // expected-error{{no matching function for call to 'operator float'}} + } +}; + +operator int(); // expected-error{{conversion function must be a non-static member function}} + +operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}} + +typedef int func_type(int); +typedef int array_type[10]; + +class Y { +public: + void operator bool(int, ...) const; // expected-error{{conversion function cannot have a return type}} \ + // expected-error{{conversion function cannot have any parameters}} + + operator float(...) const; // expected-error{{conversion function cannot be variadic}} + + + operator func_type(); // expected-error{{conversion function cannot convert to a function type}} + operator array_type(); // expected-error{{conversion function cannot convert to an array type}} +}; + + +typedef int INT; +typedef INT* INT_PTR; + +class Z { + operator int(); // expected-note {{previous declaration is here}} + operator int**(); // expected-note {{previous declaration is here}} + + operator INT(); // expected-error{{conversion function cannot be redeclared}} + operator INT_PTR*(); // expected-error{{conversion function cannot be redeclared}} +}; + + +class A { }; + +class B : public A { +public: + operator A&() const; // expected-warning{{conversion function converting 'class B' to its base class 'class A' will never be used}} + operator const void() const; // expected-warning{{conversion function converting 'class B' to 'void const' will never be used}} + operator const B(); // expected-warning{{conversion function converting 'class B' to itself will never be used}} +}; + +// This used to crash Clang. +struct Flip; +struct Flop { + Flop(); + Flop(const Flip&); +}; +struct Flip { + operator Flop() const; +}; +Flop flop = Flip(); // expected-error {{cannot initialize 'flop' with an rvalue of type 'struct Flip'}} diff --git a/test/SemaCXX/convert-to-bool.cpp b/test/SemaCXX/convert-to-bool.cpp new file mode 100644 index 0000000..937b272 --- /dev/null +++ b/test/SemaCXX/convert-to-bool.cpp @@ -0,0 +1,67 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct ConvToBool { + operator bool() const; +}; + +struct ConvToInt { + operator int(); +}; + +struct ExplicitConvToBool { + explicit operator bool(); // expected-warning{{explicit conversion functions are a C++0x extension}} +}; + +void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) { + if (ctb) { } + if (cti) { } + if (ecb) { } + for (; ctb; ) { } + for (; cti; ) { } + for (; ecb; ) { } + while (ctb) { }; + while (cti) { } + while (ecb) { } + do { } while (ctb); + do { } while (cti); + do { } while (ecb); + + if (!ctb) { } + if (!cti) { } + if (!ecb) { } + + bool b1 = !ecb; + if (ctb && ecb) { } + bool b2 = ctb && ecb; + if (ctb || ecb) { } + bool b3 = ctb || ecb; +} + +void accepts_bool(bool) { } // expected-note{{candidate function}} + +struct ExplicitConvToRef { + explicit operator int&(); // expected-warning{{explicit conversion functions are a C++0x extension}} +}; + +void test_explicit_bool(ExplicitConvToBool ecb) { + bool b1(ecb); // okay + bool b2 = ecb; // expected-error{{incompatible type initializing 'struct ExplicitConvToBool', expected 'bool'}} + accepts_bool(ecb); // expected-error{{no matching function for call to}} +} + +void test_explicit_conv_to_ref(ExplicitConvToRef ecr) { + int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot be initialized with a value of type 'struct ExplicitConvToRef'}} + int& i2(ecr); // okay +} + +struct A { }; +struct B { }; +struct C { + explicit operator A&(); // expected-warning{{explicit conversion functions are a C++0x extension}} + operator B&(); +}; + +void test_copy_init_conversions(C c) { + A &a = c; // expected-error{{non-const lvalue reference to type 'struct A' cannot be initialized with a value of type 'struct C'}} + B &b = b; // okay +} + diff --git a/test/SemaCXX/converting-constructor.cpp b/test/SemaCXX/converting-constructor.cpp new file mode 100644 index 0000000..59b793e --- /dev/null +++ b/test/SemaCXX/converting-constructor.cpp @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class Z { }; + +class Y { +public: + Y(const Z&); +}; + +class X { +public: + X(int); + X(const Y&); +}; + +void f(X); // expected-note{{candidate function}} + +void g(short s, Y y, Z z) { + f(s); + f(1.0f); + f(y); + f(z); // expected-error{{no matching function}} +} + + +class FromShort { +public: + FromShort(short s); +}; + +class FromShortExplicitly { +public: + explicit FromShortExplicitly(short s); +}; + +void explicit_constructor(short s) { + FromShort fs1(s); + FromShort fs2 = s; + FromShortExplicitly fse1(s); + FromShortExplicitly fse2 = s; // expected-error{{error: cannot initialize 'fse2' with an lvalue of type 'short'}} +} diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp new file mode 100644 index 0000000..6e5012f --- /dev/null +++ b/test/SemaCXX/copy-assignment.cpp @@ -0,0 +1,99 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct A { +}; + +struct ConvertibleToA { + operator A(); +}; + +struct ConvertibleToConstA { + operator const A(); +}; + +struct B { + B& operator=(B&); +}; + +struct ConvertibleToB { + operator B(); +}; + +struct ConvertibleToBref { + operator B&(); +}; + +struct ConvertibleToConstB { + operator const B(); +}; + +struct ConvertibleToConstBref { + operator const B&(); +}; + +struct C { + int operator=(int); // expected-note{{candidate function}} + long operator=(long); // expected-note{{candidate function}} + int operator+=(int); // expected-note{{candidate function}} + int operator+=(long); // expected-note{{candidate function}} +}; + +struct D { + D& operator+=(const D &); +}; + +struct ConvertibleToInt { + operator int(); +}; + +void test() { + A a, na; + const A constA; + ConvertibleToA convertibleToA; + ConvertibleToConstA convertibleToConstA; + + B b, nb; + const B constB; + ConvertibleToB convertibleToB; + ConvertibleToBref convertibleToBref; + ConvertibleToConstB convertibleToConstB; + ConvertibleToConstBref convertibleToConstBref; + + C c, nc; + const C constC; + + D d, nd; + const D constD; + + ConvertibleToInt convertibleToInt; + + na = a; + na = constA; + na = convertibleToA; + na = convertibleToConstA; + na += a; // expected-error{{no viable overloaded '+='}} + + nb = b; + nb = constB; // expected-error{{no viable overloaded '='}} + nb = convertibleToB; // expected-error{{no viable overloaded '='}} + nb = convertibleToBref; + nb = convertibleToConstB; // expected-error{{no viable overloaded '='}} + nb = convertibleToConstBref; // expected-error{{no viable overloaded '='}} + + nc = c; + nc = constC; + nc = 1; + nc = 1L; + nc = 1.0; // expected-error{{use of overloaded operator '=' is ambiguous}} + nc += 1; + nc += 1L; + nc += 1.0; // expected-error{{use of overloaded operator '+=' is ambiguous}} + + nd = d; + nd += d; + nd += constD; + + int i; + i = convertibleToInt; + i = a; // expected-error{{incompatible type assigning 'struct A', expected 'int'}} +} + diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp new file mode 100644 index 0000000..5b1fbaa --- /dev/null +++ b/test/SemaCXX/copy-initialization.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { +public: + explicit X(const X&); + X(int*); // expected-note{{candidate function}} + explicit X(float*); +}; + +class Y : public X { }; + +void f(Y y, int *ip, float *fp) { + X x1 = y; // expected-error{{no matching constructor for initialization of 'x1'; candidate is:}} + X x2 = 0; + X x3 = ip; + X x4 = fp; // expected-error{{cannot initialize 'x4' with an lvalue of type 'float *'}} +} + +struct foo { + void bar(); +}; + +// PR3600 +void test(const foo *P) { P->bar(); } // expected-error{{cannot initialize object parameter of type 'struct foo' with an expression of type 'struct foo const'}} diff --git a/test/SemaCXX/dcl_ambig_res.cpp b/test/SemaCXX/dcl_ambig_res.cpp new file mode 100644 index 0000000..57bf409 --- /dev/null +++ b/test/SemaCXX/dcl_ambig_res.cpp @@ -0,0 +1,66 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +// [dcl.ambig.res]p1: +struct S { + S(int); + void bar(); +}; + +int returns_an_int(); + +void foo(double a) +{ + S w(int(a)); // expected-warning{{disambiguated}} + w(17); + S x(int()); // expected-warning{{disambiguated}} + x(&returns_an_int); + S y((int)a); + y.bar(); + S z = int(a); + z.bar(); +} + +// [dcl.ambig.res]p3: +char *p; +void *operator new(__SIZE_TYPE__, int); +void foo3() { + const int x = 63; + new (int(*p)) int; //new-placement expression + new (int(*[x])); //new type-id +} + +// [dcl.ambig.res]p4: +template <class T> // expected-note{{here}} +struct S4 { + T *p; +}; +S4<int()> x; //type-id +S4<int(1)> y; // expected-error{{must be a type}} + +// [dcl.ambig.res]p5: +void foo5() +{ + (void)sizeof(int(1)); //expression + // FIXME: should we make this an error rather than a warning? + // (It affects SFINAE) + (void)sizeof(int()); // expected-warning{{function type}} +} + +// [dcl.ambig.res]p6: +void foo6() +{ + (void)(int(1)); //expression + (void)(int())1; // expected-error{{used type}} +} + +// [dcl.ambig.res]p7: +class C7 { }; +void f7(int(C7)) { } // expected-note{{candidate}} +int g7(C7); +void foo7() { + f7(1); // expected-error{{no matching function}} + f7(g7); //OK +} + +void h7(int *(C7[10])) { } // expected-note{{previous}} +void h7(int *(*_fp)(C7 _parm[10])) { } // expected-error{{redefinition}} diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp new file mode 100644 index 0000000..10c15cc --- /dev/null +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -0,0 +1,122 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +// C++ [dcl.init.aggr]p2 +struct A { + int x; + struct B { + int i; + int j; + } b; +} a1 = { 1, { 2, 3 } }; + +struct NonAggregate { + NonAggregate(); + + int a, b; +}; +NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} + +NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} + + +// C++ [dcl.init.aggr]p3 +A a_init = A(); + +// C++ [dcl.init.aggr]p4 +int x[] = { 1, 3, 5 }; +int x_sizecheck[(sizeof(x) / sizeof(int)) == 3? 1 : -1]; +int x2[] = { }; // expected-warning{{zero size arrays are an extension}} + +// C++ [dcl.init.aggr]p5 +struct StaticMemberTest { + int i; + static int s; + int *j; +} smt = { 1, &smt.i }; + +// C++ [dcl.init.aggr]p6 +char cv[4] = { 'a', 's', 'd', 'f', 0 }; // expected-error{{excess elements in array initializer}} + +// C++ [dcl.init.aggr]p7 +struct TooFew { int a; char* b; int c; }; +TooFew too_few = { 1, "asdf" }; // okay + +struct NoDefaultConstructor { // expected-note 5 {{candidate function}} + NoDefaultConstructor(int); // expected-note 5 {{candidate function}} +}; +struct TooFewError { + int a; + NoDefaultConstructor nodef; +}; +TooFewError too_few_okay = { 1, 1 }; +TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} + +TooFewError too_few_okay2[2] = { 1, 1 }; +TooFewError too_few_error2[2] = { 1 }; // expected-error{{no matching constructor}} + +NoDefaultConstructor too_few_error3[3] = { }; // expected-error 3 {{no matching constructor}} + +// C++ [dcl.init.aggr]p8 +struct Empty { }; +struct EmptyTest { + Empty s; + int i; +} empty_test = { { }, 3 }; + +EmptyTest empty_test2 = { 3 }; // expected-error{{initializer for aggregate with no elements requires explicit braces}} + +struct NonEmpty { + int a; + Empty empty; +}; +struct NonEmptyTest { + NonEmpty a, b; +} non_empty_test = { { }, { } }; + +// C++ [dcl.init.aggr]p9 +struct HasReference { + int i; + int &j; // expected-note{{uninitialized reference member is here}} +}; +int global_int; +HasReference r1 = { 1, global_int }; +HasReference r2 = { 1 } ; // expected-error{{initialization leaves reference member of type 'int &' uninitialized}} + +// C++ [dcl.init.aggr]p10 +// Note: the behavior here is identical to C +int xs[2][2] = { 3, 1, 4, 2 }; +float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; + +// C++ [dcl.init.aggr]p11 +// Note: the behavior here is identical to C +float y2[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 } }; +float same_as_y2[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; + +// C++ [dcl.init.aggr]p12 +struct A2 { + int i; + operator int *(); +}; +struct B2 { + A2 a1, a2; + int *z; +}; +struct C2 { + operator A2(); +}; +struct D2 { + operator int(); +}; +A2 a2; +C2 c2; +D2 d2; +B2 b2 = { 4, a2, a2 }; +B2 b2_2 = { 4, d2, 0 }; +B2 b2_3 = { c2, a2, a2 }; + +// C++ [dcl.init.aggr]p15: +union u { int a; char* b; }; +u u1 = { 1 }; +u u2 = u1; +u u3 = 1; // expected-error{{cannot initialize 'u3' with an rvalue of type 'int'}} +u u4 = { 0, "asdf" }; // expected-error{{excess elements in union initializer}} +u u5 = { "asdf" }; // expected-error{{incompatible type initializing 'char const [5]', expected 'int'}} diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp new file mode 100644 index 0000000..bff3334 --- /dev/null +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic-errors %s + +void f() { + int a; + struct S { int m; }; + typedef S *T; + + // Expressions. + T(a)->m = 7; + int(a)++; // expected-error {{expression is not assignable}} + __extension__ int(a)++; // expected-error {{expression is not assignable}} + __typeof(int)(a,5)<<a; // expected-error {{function-style cast to a builtin type can only take one argument}} + void(a), ++a; // expected-warning {{expression result unused}} + if (int(a)+1) {} + for (int(a)+1;;) {} + a = sizeof(int()+1); + a = sizeof(int(1)); + typeof(int()+1) a2; // expected-error {{extension used}} + (int(1)); // expected-warning {{expression result unused}} + + // type-id + (int())1; // expected-error {{used type 'int (void)' where arithmetic or pointer type is required}} + + // Declarations. + int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}} + T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-note {{previous definition is here}} + T(d)[5]; // expected-error {{redefinition of 'd'}} + typeof(int[])(f) = { 1, 2 }; // expected-error {{extension used}} + void(b)(int); + int(d2) __attribute__(()); + if (int(a)=1) {} + int(d3(int())); +} + +class C { }; +void fn(int(C)) { } // void fn(int(*fp)(C c)) { } expected-note{{candidate function}} + // not: void fn(int C); +int g(C); + +void foo() { + fn(1); // expected-error {{no matching function}} + fn(g); // OK +} diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp new file mode 100644 index 0000000..be264ad --- /dev/null +++ b/test/SemaCXX/default1.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void f(int i); +void f(int i = 0); // expected-note {{previous definition is here}} +void f(int i = 17); // expected-error {{redefinition of default argument}} + + +void g(int i, int j, int k = 3); +void g(int i, int j = 2, int k); +void g(int i = 1, int j, int k); + +void h(int i, int j = 2, int k = 3, + int l, // expected-error {{missing default argument on parameter 'l'}} + int, // expected-error {{missing default argument on parameter}} + int n);// expected-error {{missing default argument on parameter 'n'}} + +struct S { } s; +void i(int = s) { } // expected-error {{incompatible type}} + +struct X { + X(int); +}; + +void j(X x = 17); + +struct Y { + explicit Y(int); +}; + +void k(Y y = 17); // expected-error{{cannot initialize 'y' with an rvalue of type 'int'}} + +void kk(Y = 17); // expected-error{{cannot initialize a value of type 'struct Y' with an rvalue of type 'int'}} diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp new file mode 100644 index 0000000..f99e454 --- /dev/null +++ b/test/SemaCXX/default2.cpp @@ -0,0 +1,123 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f(int i, int j, int k = 3); +void f(int i, int j, int k); +void f(int i, int j = 2, int k); +void f(int i, int j, int k); +void f(int i = 1, int j, int k); +void f(int i, int j, int k); + +void i() +{ + f(); + f(0); + f(0, 1); + f(0, 1, 2); +} + + +int f1(int i, int i, int j) { // expected-error {{redefinition of parameter 'i'}} + i = 17; + return j; +} + +int x; +void g(int x, int y = x); // expected-error {{default argument references parameter 'x'}} + +void h() +{ + int i; + extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}} +} + +void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}} + +void nondecl(int (*f)(int x = 5)) // {expected-error {{default arguments can only be specified}}} +{ + void (*f2)(int = 17) // {expected-error {{default arguments can only be specified}}} + = (void (*)(int = 42))f; // {expected-error {{default arguments can only be specified}}} +} + +class X { + void f(X* x = this); // expected-error{{invalid use of 'this' outside of a nonstatic member function}} + + void g() { + int f(X* x = this); // expected-error{{default argument references 'this'}} + } +}; + +// C++ [dcl.fct.default]p6 +class C { + static int x; + void f(int i = 3); // expected-note{{previous definition is here}} + void g(int i, int j = x); + + void h(); +}; +void C::f(int i = 3) // expected-error{{redefinition of default argument}} +{ } + +void C::g(int i = 88, int j) {} + +void C::h() { + g(); // okay +} + +// C++ [dcl.fct.default]p9 +struct Y { + int a; + int mem1(int i = a); // expected-error{{invalid use of nonstatic data member 'a'}} + int mem2(int i = b); // OK; use Y::b + int mem3(int i); + int mem4(int i); + + struct Nested { + int mem5(int i = b, // OK; use Y::b + int j = c, // OK; use Y::Nested::c + int k = j, // expected-error{{default argument references parameter 'j'}} + int l = a, // expected-error{{invalid use of nonstatic data member 'a'}} + Nested* self = this, // expected-error{{invalid use of 'this' outside of a nonstatic member function}} + int m); // expected-error{{missing default argument on parameter 'm'}} + static int c; + }; + + static int b; + + int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}} + + void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}} +}; + +int Y::mem3(int i = b) { return i; } // OK; use X::b + +int Y::mem4(int i = a) // expected-error{{invalid use of nonstatic data member 'a'}} +{ return i; } + + +// Try to verify that default arguments interact properly with copy +// constructors. +class Z { +public: + Z(Z&, int i = 17); // expected-note 2 {{candidate function}} + + void f(Z& z) { + Z z2; // expected-error{{no matching constructor for initialization}} + Z z3(z); + } + + void test_Z(const Z& z) { + Z z2(z); // expected-error{{no matching constructor for initialization of 'z2'}} + } +}; + +void test_Z(const Z& z) { + Z z2(z); // expected-error{{no matching constructor for initialization of 'z2'}} +} + +struct ZZ { + void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}} + + static ZZ g(int = 17); + + ZZ(ZZ&, int = 17); // expected-note{{candidate function}} +}; diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp new file mode 100644 index 0000000..8064ed3 --- /dev/null +++ b/test/SemaCXX/deleted-function.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +int i = delete; // expected-error {{only functions can have deleted definitions}} + +void fn() = delete; // expected-note {{candidate function has been explicitly deleted}} + +void fn2(); // expected-note {{previous declaration is here}} +void fn2() = delete; // expected-error {{deleted definition must be first declaration}} + +void fn3() = delete; +void fn3() { + // FIXME: This definition should be invalid. +} + +void ov(int) {} // expected-note {{candidate function}} +void ov(double) = delete; // expected-note {{candidate function has been explicitly deleted}} + +struct WithDel { + WithDel() = delete; // expected-note {{candidate function has been explicitly deleted}} + void fn() = delete; // expected-note {{function has been explicitly marked deleted here}} + operator int() = delete; + void operator +(int) = delete; + + int i = delete; // expected-error {{only functions can have deleted definitions}} +}; + +void test() { + fn(); // expected-error {{call to deleted function 'fn'}} + ov(1); + ov(1.0); // expected-error {{call to deleted function 'ov'}} + + WithDel dd; // expected-error {{call to deleted constructor of 'dd'}} + WithDel *d = 0; + d->fn(); // expected-error {{attempt to use a deleted function}} + int i = *d; // expected-error {{incompatible type initializing}} +} diff --git a/test/SemaCXX/dependent-types.cpp b/test/SemaCXX/dependent-types.cpp new file mode 100644 index 0000000..b2a5c45 --- /dev/null +++ b/test/SemaCXX/dependent-types.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +template<typename T, int Size> void f() { + T x1; + T* x2; + T& x3; // expected-error{{declaration of reference variable 'x3' requires an initializer}} + T x4[]; // expected-error{{variable has incomplete type 'T []'}} + T x5[Size]; + int x6[Size]; +} diff --git a/test/SemaCXX/derived-to-base-ambig.cpp b/test/SemaCXX/derived-to-base-ambig.cpp new file mode 100644 index 0000000..e15ddde --- /dev/null +++ b/test/SemaCXX/derived-to-base-ambig.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { }; +class B : public A { }; +class C : public A { }; +class D : public B, public C { }; + +void f(D* d) { + A* a; + a = d; // expected-error{{ambiguous conversion from derived class 'class D' to base class 'class A'}} expected-error{{incompatible type assigning 'class D *', expected 'class A *'}} +} + +class Object2 { }; +class A2 : public Object2 { }; +class B2 : public virtual A2 { }; +class C2 : virtual public A2 { }; +class D2 : public B2, public C2 { }; +class E2 : public D2, public C2, public virtual A2 { }; +class F2 : public E2, public A2 { }; + +void g(E2* e2, F2* f2) { + Object2* o2; + o2 = e2; + o2 = f2; // expected-error{{ambiguous conversion from derived class 'class F2' to base class 'class Object2'}} expected-error{{incompatible type assigning 'class F2 *', expected 'class Object2 *'}} +} + +// Test that ambiguous/inaccessibility checking does not trigger too +// early, because it should not apply during overload resolution. +void overload_okay(Object2*); +void overload_okay(E2*); + +void overload_call(F2* f2) { + overload_okay(f2); +} diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp new file mode 100644 index 0000000..f544db0 --- /dev/null +++ b/test/SemaCXX/destructor.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { +public: + ~A(); +}; + +class B { +public: + ~B() { } +}; + +class C { +public: + (~C)() { } +}; + +struct D { + static void ~D(int, ...) const { } // \ + // expected-error{{type qualifier is not allowed on this function}} \ + // expected-error{{destructor cannot be declared 'static'}} \ + // expected-error{{destructor cannot have any parameters}} \ + // expected-error{{destructor cannot be variadic}} +}; + +struct D2 { + void ~D2() { } // \ + // expected-error{{destructor cannot have a return type}} +}; + + +struct E; + +typedef E E_typedef; +struct E { + ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'struct E') of the class name}} +}; + +struct F { + (~F)(); // expected-note {{previous declaration is here}} + ~F(); // expected-error {{destructor cannot be redeclared}} +}; + +~; // expected-error {{expected class name}} +~undef(); // expected-error {{expected class name}} +~F(){} // expected-error {{destructor must be a non-static member function}} + +struct G { + ~G(); +}; + +G::~G() { } + +// <rdar://problem/6841210> +struct H { + ~H(void) { } +}; diff --git a/test/SemaCXX/direct-initializer.cpp b/test/SemaCXX/direct-initializer.cpp new file mode 100644 index 0000000..149b65c --- /dev/null +++ b/test/SemaCXX/direct-initializer.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int x(1); +int (x2)(1); + +void f() { + int x(1); + int (x2)(1); + for (int x(1);;) {} +} + +class Y { + explicit Y(float); +}; + +class X { // expected-note{{candidate function}} +public: + explicit X(int); // expected-note{{candidate function}} + X(float, float, float); // expected-note{{candidate function}} + X(float, Y); // expected-note{{candidate function}} +}; + +class Z { +public: + Z(int); +}; + +void g() { + X x1(5); + X x2(1.0, 3, 4.2); + X x3(1.0, 1.0); // expected-error{{no matching constructor for initialization of 'x3'; candidates are:}} + Y y(1.0); + X x4(3.14, y); + + Z z; // expected-error{{no matching constructor for initialization of 'z'}} +} diff --git a/test/SemaCXX/do-while-scope.cpp b/test/SemaCXX/do-while-scope.cpp new file mode 100644 index 0000000..4e4a483 --- /dev/null +++ b/test/SemaCXX/do-while-scope.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void test() { + int x; + do + int x; + while (1); +} diff --git a/test/SemaCXX/dynamic-cast.cpp b/test/SemaCXX/dynamic-cast.cpp new file mode 100644 index 0000000..42c5e01 --- /dev/null +++ b/test/SemaCXX/dynamic-cast.cpp @@ -0,0 +1,74 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; +struct B : A {}; +struct C : B {}; + +struct D : private A {}; +struct E : A {}; +struct F : B, E {}; + +struct Incomplete; // expected-note 2 {{forward declaration of 'struct Incomplete'}} + +struct Poly +{ + virtual void f(); +}; + +struct PolyDerived : Poly +{ +}; + +void basic_bad() +{ + // ptr -> nonptr + (void)dynamic_cast<A>((A*)0); // expected-error {{'struct A' is not a reference or pointer}} + // nonptr -> ptr + (void)dynamic_cast<A*>(0); // expected-error {{'int' is not a pointer}} + // ptr -> noncls + (void)dynamic_cast<int*>((A*)0); // expected-error {{'int' is not a class}} + // noncls -> ptr + (void)dynamic_cast<A*>((int*)0); // expected-error {{'int' is not a class}} + // ref -> noncls + (void)dynamic_cast<int&>(*((A*)0)); // expected-error {{'int' is not a class}} + // noncls -> ref + (void)dynamic_cast<A&>(*((int*)0)); // expected-error {{'int' is not a class}} + // ptr -> incomplete + (void)dynamic_cast<Incomplete*>((A*)0); // expected-error {{'struct Incomplete' is an incomplete type}} + // incomplete -> ptr + (void)dynamic_cast<A*>((Incomplete*)0); // expected-error {{'struct Incomplete' is an incomplete type}} +} + +void same() +{ + (void)dynamic_cast<A*>((A*)0); + (void)dynamic_cast<A&>(*((A*)0)); +} + +void up() +{ + (void)dynamic_cast<A*>((B*)0); + (void)dynamic_cast<A&>(*((B*)0)); + (void)dynamic_cast<A*>((C*)0); + (void)dynamic_cast<A&>(*((C*)0)); + + // Inaccessible + //(void)dynamic_cast<A*>((D*)0); + //(void)dynamic_cast<A&>(*((D*)0)); + + // Ambiguous + (void)dynamic_cast<A*>((F*)0); // expected-error {{ambiguous conversion from derived class 'struct F' to base class 'struct A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} + (void)dynamic_cast<A&>(*((F*)0)); // expected-error {{ambiguous conversion from derived class 'struct F' to base class 'struct A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} +} + +void poly() +{ + (void)dynamic_cast<A*>((Poly*)0); + (void)dynamic_cast<A&>(*((Poly*)0)); + (void)dynamic_cast<A*>((PolyDerived*)0); + (void)dynamic_cast<A&>(*((PolyDerived*)0)); + + // Not polymorphic source + (void)dynamic_cast<Poly*>((A*)0); // expected-error {{'struct A' is not polymorphic}} + (void)dynamic_cast<PolyDerived&>(*((A*)0)); // expected-error {{'struct A' is not polymorphic}} +} diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp new file mode 100644 index 0000000..70478e0 --- /dev/null +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -0,0 +1,47 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Test the use of elaborated-type-specifiers to inject the names of +// structs (or classes or unions) into an outer scope as described in +// C++ [basic.scope.pdecl]p5. +typedef struct S1 { + union { + struct S2 *x; + struct S3 *y; + }; +} S1; + +bool test_elab(S1 *s1, struct S2 *s2, struct S3 *s3) { + if (s1->x == s2) return true; + if (s1->y == s3) return true; + return false; +} + +namespace NS { + class X { + public: + void test_elab2(struct S4 *s4); + }; + + void X::test_elab2(S4 *s4) { } +} + +void test_X_elab(NS::X x) { + struct S4 *s4 = 0; + x.test_elab2(s4); // expected-error{{incompatible type passing 'struct S4 *', expected 'struct NS::S4 *'}} +} + +namespace NS { + S4 *get_S4(); +} + +void test_S5_scope() { + S4 *s4; // expected-error{{use of undeclared identifier 'S4'}} +} + +int test_funcparam_scope(struct S5 * s5) { + struct S5 { int y; } *s5_2 = 0; + if (s5 == s5_2) return 1; // expected-error {{comparison of distinct pointer types ('struct S5 *' and 'struct S5 *')}} + return 0; +} + + diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp new file mode 100644 index 0000000..9668c84 --- /dev/null +++ b/test/SemaCXX/enum.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s +enum E { + Val1, + Val2 +}; + +int& enumerator_type(int); +float& enumerator_type(E); + +void f() { + E e = Val1; + float& fr = enumerator_type(Val2); +} + +// <rdar://problem/6502934> +typedef enum Foo { + A = 0, + B = 1 +} Foo; + + +void bar() { + Foo myvar = A; + myvar = B; +} + +/// PR3688 +struct s1 { + enum e1 (*bar)(void); // expected-error{{ISO C++ forbids forward references to 'enum' types}} expected-note{{forward declaration of 'enum s1::e1'}} +}; + +enum e1 { YES, NO }; + +static enum e1 badfunc(struct s1 *q) { + return q->bar(); // expected-error{{return type of called function ('enum s1::e1') is incomplete}} +} + +enum e2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp new file mode 100644 index 0000000..ea02aac --- /dev/null +++ b/test/SemaCXX/exception-spec.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Straight from the standard: +// Plain function with spec +void f() throw(int); +// Pointer to function with spec +void (*fp)() throw (int); +// Function taking reference to function with spec +void g(void pfa() throw(int)); +// Typedef for pointer to function with spec +typedef int (*pf)() throw(int); // expected-error {{specifications are not allowed in typedefs}} + +// Some more: +// Function returning function with spec +void (*h())() throw(int); +// Ultimate parser thrill: function with spec returning function with spec and +// taking pointer to function with spec. +// The actual function throws int, the return type double, the argument float. +void (*i() throw(int))(void (*)() throw(float)) throw(double); +// Pointer to pointer to function taking function with spec +void (**k)(void pfa() throw(int)); // no-error +// Pointer to pointer to function with spec +void (**j)() throw(int); // expected-error {{not allowed beyond a single}} +// Pointer to function returning pointer to pointer to function with spec +void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}} + +struct Incomplete; + +// Exception spec must not have incomplete types, or pointers to them, except +// void. +void ic1() throw(void); // expected-error {{incomplete type 'void' is not allowed in exception specification}} +void ic2() throw(Incomplete); // expected-error {{incomplete type 'struct Incomplete' is not allowed in exception specification}} +void ic3() throw(void*); +void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'struct Incomplete' is not allowed in exception specification}} +void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'struct Incomplete' is not allowed in exception specification}} diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp new file mode 100644 index 0000000..5882b9c --- /dev/null +++ b/test/SemaCXX/exceptions.cpp @@ -0,0 +1,99 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A; // expected-note 4 {{forward declaration of 'struct A'}} + +struct Abstract { virtual void f() = 0; }; // expected-note {{pure virtual function 'f'}} + +void trys() { + try { + } catch(int i) { // expected-note {{previous definition}} + int j = i; + int i; // expected-error {{redefinition of 'i'}} + } catch(float i) { + } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}} + } catch(A a) { // expected-error {{cannot catch incomplete type 'struct A'}} + } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'struct A'}} + } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'struct A'}} + } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}} + } catch(...) { + int j = i; // expected-error {{use of undeclared identifier 'i'}} + } + + try { + } catch(...) { // expected-error {{catch-all handler must come last}} + } catch(int) { + } +} + +void throws() { + throw; + throw 0; + throw throw; // expected-error {{cannot throw object of incomplete type 'void'}} + throw (A*)0; // expected-error {{cannot throw pointer to object of incomplete type 'struct A'}} +} + +void jumps() { +l1: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; + try { // expected-note 4 {{jump bypasses initialization of try block}} + l2: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; + goto l1; + } catch(int) { // expected-note 4 {{jump bypasses initialization of catch block}} + l3: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; + } catch(...) { // expected-note 4 {{jump bypasses initialization of catch block}} + l4: + goto l5; + goto l4; + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; + } +l5: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; +} + +struct BadReturn { + BadReturn() try { + } catch(...) { + // Try to hide + try { + } catch(...) { + { + if (0) + return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} + } + } + } + BadReturn(int); +}; + +BadReturn::BadReturn(int) try { +} catch(...) { + // Try to hide + try { + } catch(int) { + return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} + } catch(...) { + { + if (0) + return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} + } + } +} diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp new file mode 100644 index 0000000..6a2f30d --- /dev/null +++ b/test/SemaCXX/expressions.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void choice(int); +int choice(bool); + +void test() { + // Result of ! must be type bool. + int i = choice(!1); +} diff --git a/test/SemaCXX/fntype-decl.cpp b/test/SemaCXX/fntype-decl.cpp new file mode 100644 index 0000000..ae85ff4 --- /dev/null +++ b/test/SemaCXX/fntype-decl.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR2942 +typedef void fn(int); +fn f; // expected-note {{previous declaration is here}} + +int g(int x, int y); +int g(int x, int y = 2); + +typedef int g_type(int, int); +g_type g; + +int h(int x) { // expected-note {{previous definition is here}} + return g(x); +} + +float f(int) { } // expected-error{{functions that differ only in their return type cannot be overloaded}} + +int h(int) { } // expected-error{{redefinition of 'h'}} + diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp new file mode 100644 index 0000000..76e84e5 --- /dev/null +++ b/test/SemaCXX/friend.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +friend class A; // expected-error {{'friend' used outside of class}} +void f() { friend class A; } // expected-error {{'friend' used outside of class}} +class C { friend class A; }; +class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}} diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp new file mode 100644 index 0000000..9f67837 --- /dev/null +++ b/test/SemaCXX/function-redecl.cpp @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int foo(int); + +namespace N { + void f1() { + void foo(int); // okay + } + + // FIXME: we shouldn't even need this declaration to detect errors + // below. + void foo(int); // expected-note{{previous declaration is here}} + + void f2() { + int foo(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} + + { + int foo; + { + // FIXME: should diagnose this because it's incompatible with + // N::foo. However, name lookup isn't properly "skipping" the + // "int foo" above. + float foo(int); + } + } + } +} diff --git a/test/SemaCXX/function-type-qual.cpp b/test/SemaCXX/function-type-qual.cpp new file mode 100644 index 0000000..f1d5aac --- /dev/null +++ b/test/SemaCXX/function-type-qual.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() const; // expected-error {{type qualifier is not allowed on this function}} + +typedef void cfn() const; +cfn f2; // expected-error {{a qualified function type cannot be used to declare a nonmember function or a static member function}} + +class C { + void f() const; + cfn f2; + static void f3() const; // expected-error {{type qualifier is not allowed on this function}} + static cfn f4; // expected-error {{a qualified function type cannot be used to declare a nonmember function or a static member function}} + + void m1() { + x = 0; + } + + void m2() const { + x = 0; // expected-error {{read-only variable is not assignable}} + } + + int x; +}; diff --git a/test/SemaCXX/functional-cast.cpp b/test/SemaCXX/functional-cast.cpp new file mode 100644 index 0000000..0be7ddb --- /dev/null +++ b/test/SemaCXX/functional-cast.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct SimpleValueInit { + int i; +}; + +struct InitViaConstructor { + InitViaConstructor(int i = 7); +}; + +// FIXME: error messages for implicitly-declared special member +// function candidates are very poor +struct NoValueInit { // expected-note 2 {{candidate function}} + NoValueInit(int i, int j); // expected-note 2 {{candidate function}} +}; + +void test_cxx_functional_value_init() { + (void)SimpleValueInit(); + (void)InitViaConstructor(); + (void)NoValueInit(); // expected-error{{no matching constructor for initialization}} +} + +void test_cxx_function_cast_multi() { + (void)NoValueInit(0, 0); + (void)NoValueInit(0, 0, 0); // expected-error{{no matching constructor for initialization}} + (void)int(1, 2); // expected-error{{function-style cast to a builtin type can only take one argument}} +} diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp new file mode 100644 index 0000000..32d04e2 --- /dev/null +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// C++-specific tests for integral constant expressions. + +const int c = 10; +int ar[c]; diff --git a/test/SemaCXX/implicit-int.cpp b/test/SemaCXX/implicit-int.cpp new file mode 100644 index 0000000..6fa8dd3 --- /dev/null +++ b/test/SemaCXX/implicit-int.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +x; // expected-error{{C++ requires a type specifier for all declarations}} + +f(int y) { return y; } // expected-error{{C++ requires a type specifier for all declarations}} diff --git a/test/SemaCXX/inherit.cpp b/test/SemaCXX/inherit.cpp new file mode 100644 index 0000000..eaad97cc --- /dev/null +++ b/test/SemaCXX/inherit.cpp @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { }; + +class B1 : A { }; + +class B2 : virtual A { }; + +class B3 : virtual virtual A { }; // expected-error{{duplicate 'virtual' in base specifier}} + +class C : public B1, private B2 { }; + + +class D; // expected-note {{forward declaration of 'class D'}} + +class E : public D { }; // expected-error{{base class has incomplete type}} + +typedef int I; + +class F : public I { }; // expected-error{{base specifier must name a class}} + +union U1 : public A { }; // expected-error{{unions cannot have base classes}} + +union U2 {}; + +class G : public U2 { }; // expected-error{{unions cannot be base classes}} + +typedef G G_copy; +typedef G G_copy_2; +typedef G_copy G_copy_3; + +class H : G_copy, A, G_copy_2, // expected-error{{base class 'G_copy' (aka 'class G') specified more than once as a direct base class}} + public G_copy_3 { }; // expected-error{{base class 'G_copy' (aka 'class G') specified more than once as a direct base class}} diff --git a/test/SemaCXX/inline.cpp b/test/SemaCXX/inline.cpp new file mode 100644 index 0000000..7d0505a --- /dev/null +++ b/test/SemaCXX/inline.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Check that we don't allow illegal uses of inline +// (checking C++-only constructs here) +struct c {inline int a;}; // expected-error{{'inline' can only appear on functions}} diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp new file mode 100644 index 0000000..864953e --- /dev/null +++ b/test/SemaCXX/linkage-spec.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s +extern "C" { + extern "C" void f(int); +} + +extern "C++" { + extern "C++" int& g(int); + float& g(); +} +double& g(double); + +void test(int x, double d) { + f(x); + float &f1 = g(); + int& i1 = g(x); + double& d1 = g(d); +} + +extern "C" int foo; +extern "C" int foo; + +extern "C" const int bar; +extern "C" int const bar; + +// <rdar://problem/6895431> +extern "C" struct bar d; +extern struct bar e; diff --git a/test/SemaCXX/member-expr-static.cpp b/test/SemaCXX/member-expr-static.cpp new file mode 100644 index 0000000..b6495a8 --- /dev/null +++ b/test/SemaCXX/member-expr-static.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef void (*thread_continue_t)(); + +extern "C" { +extern void kernel_thread_start(thread_continue_t continuation); +extern void pure_c(void); +} + +class _IOConfigThread +{ +public: + static void main( void ); +}; + + +void foo( void ) +{ + kernel_thread_start(&_IOConfigThread::main); + kernel_thread_start((thread_continue_t)&_IOConfigThread::main); + kernel_thread_start(&pure_c); +} diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp new file mode 100644 index 0000000..60ee10d --- /dev/null +++ b/test/SemaCXX/member-expr.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class X{ +public: + enum E {Enumerator}; + int f(); + static int mem; + static float g(); +}; + +void test(X* xp, X x) { + int i1 = x.f(); + int i2 = xp->f(); + x.E; // expected-error{{cannot refer to type member 'E' with '.'}} + xp->E; // expected-error{{cannot refer to type member 'E' with '->'}} + int i3 = x.Enumerator; + int i4 = xp->Enumerator; + x.mem = 1; + xp->mem = 2; + float f1 = x.g(); + float f2 = xp->g(); +} + +struct A { + int f0; +}; +struct B { + A *f0(); +}; +int f0(B *b) { + return b->f0->f0; // expected-error{{member reference base type 'struct A *(void)' is not a structure or union}} \ + // expected-note{{perhaps you meant to call this function}} +} diff --git a/test/SemaCXX/member-location.cpp b/test/SemaCXX/member-location.cpp new file mode 100644 index 0000000..cb53ae1 --- /dev/null +++ b/test/SemaCXX/member-location.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR4103: Make sure we have a location for the error +class A { float a(int *); int b(); }; +int A::b() { return a(a((int*)0)); } // expected-error {{incompatible type}} + diff --git a/test/SemaCXX/member-name-lookup.cpp b/test/SemaCXX/member-name-lookup.cpp new file mode 100644 index 0000000..9fcd922 --- /dev/null +++ b/test/SemaCXX/member-name-lookup.cpp @@ -0,0 +1,148 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct A { + int a; // expected-note 4{{member found by ambiguous name lookup}} + static int b; + static int c; // expected-note 4{{member found by ambiguous name lookup}} + + enum E { enumerator }; + + typedef int type; + + static void f(int); + void f(float); // expected-note 2{{member found by ambiguous name lookup}} + + static void static_f(int); + static void static_f(double); +}; + +struct B : A { + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E2 { enumerator2 }; + + enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct C : A { + int c; // expected-note 2{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct D : B, C { + void test_lookup(); +}; + +void test_lookup(D d) { + d.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + (void)d.b; // okay + d.c; // expected-error{{member 'c' found in multiple base classes of different types}} + d.d; // expected-error{{member 'd' found in multiple base classes of different types}} + d.f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'struct A'}} + d.static_f(0); // okay + + D::E e = D::enumerator; // okay + D::type t = 0; // okay + + D::E2 e2 = D::enumerator2; // okay + + D::E3 e3; // expected-error{{multiple base classes}} +} + +void D::test_lookup() { + a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + (void)b; // okay + c; // expected-error{{member 'c' found in multiple base classes of different types}} + d; // expected-error{{member 'd' found in multiple base classes of different types}} + f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'struct A'}} + static_f(0); // okay + + E e = enumerator; // okay + type t = 0; // okay + + E2 e2 = enumerator2; // okay + + E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} +} + +struct B2 : virtual A { + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E2 { enumerator2 }; + + enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}} +}; + +struct C2 : virtual A { + int c; // expected-note 2{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct D2 : B2, C2 { + void test_virtual_lookup(); +}; + +struct F : A { }; +struct G : F, D2 { + void test_virtual_lookup(); +}; + +void test_virtual_lookup(D2 d2, G g) { + (void)d2.a; + (void)d2.b; + d2.c; // expected-error{{member 'c' found in multiple base classes of different types}} + d2.d; // expected-error{{member 'd' found in multiple base classes of different types}} + d2.f(0); // okay + d2.static_f(0); // okay + + D2::E e = D2::enumerator; // okay + D2::type t = 0; // okay + + D2::E2 e2 = D2::enumerator2; // okay + + D2::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} + + g.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + g.static_f(0); // okay +} + +void D2::test_virtual_lookup() { + (void)a; + (void)b; + c; // expected-error{{member 'c' found in multiple base classes of different types}} + d; // expected-error{{member 'd' found in multiple base classes of different types}} + f(0); // okay + static_f(0); // okay + + E e = enumerator; // okay + type t = 0; // okay + + E2 e2 = enumerator2; // okay + + E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} +} + +void G::test_virtual_lookup() { + a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + static_f(0); // okay +} + + +struct HasMemberType1 { + struct type { }; // expected-note{{member found by ambiguous name lookup}} +}; + +struct HasMemberType2 { + struct type { }; // expected-note{{member found by ambiguous name lookup}} +}; + +struct HasAnotherMemberType : HasMemberType1, HasMemberType2 { + struct type { }; +}; + +struct UsesAmbigMemberType : HasMemberType1, HasMemberType2 { + type t; // expected-error{{member 'type' found in multiple base classes of different types}} +}; diff --git a/test/SemaCXX/member-pointer-size.cpp b/test/SemaCXX/member-pointer-size.cpp new file mode 100644 index 0000000..f86e72b --- /dev/null +++ b/test/SemaCXX/member-pointer-size.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify && +// RUN: clang-cc -triple i686-unknown-unknown %s -fsyntax-only -verify +#include <stddef.h> + +struct A; + +void f() { + int A::*dataMember; + + int (A::*memberFunction)(); + + typedef int assert1[sizeof(dataMember) == sizeof(ptrdiff_t) ? 1 : -1]; + typedef int assert2[sizeof(memberFunction) == sizeof(ptrdiff_t) * 2 ? 1 : -1]; +} + diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp new file mode 100644 index 0000000..cfe4f75 --- /dev/null +++ b/test/SemaCXX/member-pointer.cpp @@ -0,0 +1,129 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; +enum B { Dummy }; +namespace C {} +struct D : A {}; +struct E : A {}; +struct F : D, E {}; +struct G : virtual D {}; + +int A::*pdi1; +int (::A::*pdi2); +int (A::*pfi)(int); + +int B::*pbi; // expected-error {{expected a class or namespace}} +int C::*pci; // expected-error {{'pci' does not point into a class}} +void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}} +int& A::*pdr; // expected-error {{'pdr' declared as a pointer to a reference}} + +void f() { + // This requires tentative parsing. + int (A::*pf)(int, int); + + // Implicit conversion to bool. + bool b = pdi1; + b = pfi; + + // Conversion from null pointer constant. + pf = 0; + pf = __null; + + // Conversion to member of derived. + int D::*pdid = pdi1; + pdid = pdi2; + + // Fail conversion due to ambiguity and virtuality. + int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'struct A' to pointer to member of derived class 'struct F'}} expected-error {{incompatible type}} + int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'struct A' to pointer to member of class 'struct G' via virtual base 'struct D' is not allowed}} expected-error {{incompatible type}} + + // Conversion to member of base. + pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}} +} + +struct TheBase +{ + void d(); +}; + +struct HasMembers : TheBase +{ + int i; + void f(); + + void g(); + void g(int); + static void g(double); +}; + +namespace Fake +{ + int i; + void f(); +} + +void g() { + HasMembers hm; + + int HasMembers::*pmi = &HasMembers::i; + int *pni = &Fake::i; + int *pmii = &hm.i; + + void (HasMembers::*pmf)() = &HasMembers::f; + void (*pnf)() = &Fake::f; + &hm.f; // FIXME: needs diagnostic expected-warning{{result unused}} + + void (HasMembers::*pmgv)() = &HasMembers::g; + void (HasMembers::*pmgi)(int) = &HasMembers::g; + void (*pmgd)(double) = &HasMembers::g; + + void (HasMembers::*pmd)() = &HasMembers::d; +} + +struct Incomplete; + +void h() { + HasMembers hm, *phm = &hm; + + int HasMembers::*pi = &HasMembers::i; + hm.*pi = 0; + int i = phm->*pi; + (void)&(hm.*pi); + (void)&(phm->*pi); + (void)&((&hm)->*pi); // expected-error {{address expression must be an lvalue or a function designator}} + + void (HasMembers::*pf)() = &HasMembers::f; + (hm.*pf)(); + (phm->*pf)(); + + (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct HasMembers'}} + (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct HasMembers *'}} + (void)(i.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'int'}} + int *ptr; + (void)(ptr->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'int *'}} + + int A::*pai = 0; + D d, *pd = &d; + (void)(d.*pai); + (void)(pd->*pai); + F f, *ptrf = &f; + (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct F'}} + (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct F *'}} + + (void)(hm.*i); // expected-error {{pointer-to-member}} + (void)(phm->*i); // expected-error {{pointer-to-member}} + + Incomplete *inc; + int Incomplete::*pii = 0; + (void)(inc->*pii); // okay +} + +struct OverloadsPtrMem +{ + int operator ->*(const char *); +}; + +void i() { + OverloadsPtrMem m; + int foo = m->*"Awesome!"; +} diff --git a/test/SemaCXX/ms-exception-spec.cpp b/test/SemaCXX/ms-exception-spec.cpp new file mode 100644 index 0000000..b84ea17 --- /dev/null +++ b/test/SemaCXX/ms-exception-spec.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fms-extensions + +void f() throw(...) { } diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp new file mode 100644 index 0000000..d5e4238 --- /dev/null +++ b/test/SemaCXX/namespace-alias.cpp @@ -0,0 +1,64 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { }; + +namespace A = N; + +int B; // expected-note {{previous definition is here}} +namespace B = N; // expected-error {{redefinition of 'B' as different kind of symbol}} + +namespace C { } // expected-note {{previous definition is here}} +namespace C = N; // expected-error {{redefinition of 'C'}} + +int i; +namespace D = i; // expected-error {{expected namespace name}} + +namespace E = N::Foo; // expected-error {{expected namespace name}} + +namespace F { + namespace A { namespace B { } } // expected-note {{candidate found by name lookup is 'F::A::B'}} + namespace B { } // expected-note {{candidate found by name lookup is 'F::B'}} + using namespace A; + namespace D = B; // expected-error {{reference to 'B' is ambiguous}} +} + +namespace G { + namespace B = N; +} + +namespace H { + namespace A1 { } + namespace A2 { } + + // These all point to A1. + namespace B = A1; // expected-note {{previous definition is here}} + namespace B = A1; + namespace C = B; + namespace B = C; + + namespace B = A2; // expected-error {{redefinition of 'B' as different kind of symbol}} +} + +namespace I { + namespace A1 { int i; } + + namespace A2 = A1; +} + +int f() { + return I::A2::i; +} + +namespace J { + namespace A { + namespace B { void func (); } + } + + namespace C = A; + + using namespace C::B; + + void g() { + func(); + } +} diff --git a/test/SemaCXX/namespace.cpp b/test/SemaCXX/namespace.cpp new file mode 100644 index 0000000..696ea81 --- /dev/null +++ b/test/SemaCXX/namespace.cpp @@ -0,0 +1,69 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace A { // expected-note 2 {{previous definition is here}} + int A; + void f() { A = 0; } +} + +void f() { A = 0; } // expected-error {{unexpected namespace name 'A': expected expression}} +int A; // expected-error {{redefinition of 'A' as different kind of symbol}} +class A; // expected-error {{redefinition of 'A' as different kind of symbol}} + +class B {}; // expected-note {{previous definition is here}} + +void C(); // expected-note {{previous definition is here}} +namespace C {} // expected-error {{redefinition of 'C' as different kind of symbol}} + +namespace D { + class D {}; +} + +namespace S1 { + int x; + + namespace S2 { + + namespace S3 { + B x; + } + } +} + +namespace S1 { + void f() { + x = 0; + } + + namespace S2 { + + namespace S3 { + void f() { + x = 0; // expected-error {{no viable overloaded '='}} + } + } + + int y; + } +} + +namespace S1 { + namespace S2 { + namespace S3 { + void f3() { + y = 0; + } + } + } +} + +namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}} + + +namespace foo { + enum x { + Y + }; +} + +static foo::x test1; // ok + +static foo::X test2; // typo: expected-error {{unknown type name 'X'}} diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp new file mode 100644 index 0000000..4c3ecee --- /dev/null +++ b/test/SemaCXX/nested-name-spec.cpp @@ -0,0 +1,173 @@ +// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s +namespace A { + struct C { + static int cx; + + static int cx2; + + static int Ag1(); + static int Ag2(); + }; + int ax; + void Af(); +} + +A:: ; // expected-error {{expected unqualified-id}} +::A::ax::undef ex3; // expected-error {{expected a class or namespace}} expected-error {{unknown type name 'undef'}} +A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{unknown type name 'undef2'}} + +int A::C::Ag1() { return 0; } + +static int A::C::Ag2() { return 0; } // expected-error{{'static' can}} + +int A::C::cx = 17; + + +static int A::C::cx2 = 17; // expected-error{{'static' can}} + +class C2 { + void m(); // expected-note{{member declaration nearly matches}} + + void f(const int& parm); // expected-note{{member declaration nearly matches}} + void f(int) const; // expected-note{{member declaration nearly matches}} + void f(float); + + int x; +}; + +void C2::m() const { } // expected-error{{out-of-line definition does not match any declaration in 'C2'}} + +void C2::f(int) { } // expected-error{{out-of-line definition does not match any declaration in 'C2'}} + +void C2::m() { + x = 0; +} + +namespace B { + void ::A::Af() {} // expected-error {{definition or redeclaration of 'Af' not in a namespace enclosing 'A'}} +} + +void f1() { + void A::Af(); // expected-error {{definition or redeclaration of 'Af' not allowed inside a function}} +} + +void f2() { + A:: ; // expected-error {{expected unqualified-id}} + A::C::undef = 0; // expected-error {{no member named 'undef'}} + ::A::C::cx = 0; + int x = ::A::ax = A::C::cx; + x = sizeof(A::C); + x = sizeof(::A::C::cx); +} + +A::C c1; +struct A::C c2; +struct S : public A::C {}; +struct A::undef; // expected-error {{'undef' does not name a tag member in the specified scope}} + +namespace A2 { + typedef int INT; + struct RC; + struct CC { + struct NC; + }; +} + +struct A2::RC { + INT x; +}; + +struct A2::CC::NC { + void m() {} +}; + +void f3() { + N::x = 0; // expected-error {{use of undeclared identifier 'N'}} + int N; + N::x = 0; // expected-error {{expected a class or namespace}} + { int A; A::ax = 0; } + { typedef int A; A::ax = 0; } // expected-error{{expected a class or namespace}} + { int A(); A::ax = 0; } + { typedef A::C A; A::ax = 0; } // expected-error {{no member named 'ax'}} + { typedef A::C A; A::cx = 0; } +} + +// make sure the following doesn't hit any asserts +void f4(undef::C); // expected-error {{use of undeclared identifier 'undef'}} \ + expected-error {{variable has incomplete type 'void'}} + +typedef void C2::f5(int); // expected-error{{typedef declarator cannot be qualified}} + +void f6(int A2::RC::x); // expected-error{{parameter declarator cannot be qualified}} + +int A2::RC::x; // expected-error{{non-static data member defined out-of-line}} + +void A2::CC::NC::m(); // expected-error{{out-of-line declaration of a member must be a definition}} + + +namespace E { + int X = 5; + + namespace Nested { + enum E { + X = 0 + }; + + void f() { + return E::X; // expected-error{{expected a class or namespace}} + } + } +} + + +class Operators { + Operators operator+(const Operators&) const; // expected-note{{member declaration nearly matches}} + operator bool(); +}; + +Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition does not match any declaration in 'Operators'}} + Operators ops; + return ops; +} + +Operators Operators::operator+(const Operators&) const { + Operators ops; + return ops; +} + +Operators::operator bool() { + return true; +} + +namespace A { + void g(int&); // expected-note{{member declaration nearly matches}} +} + +void A::f() {} // expected-error{{out-of-line definition does not match any declaration in 'A'}} + +void A::g(const int&) { } // expected-error{{out-of-line definition does not match any declaration in 'A'}} + +struct Struct { }; + +void Struct::f() { } // expected-error{{out-of-line definition does not match any declaration in 'Struct'}} + +void global_func(int); +void global_func2(int); + +namespace N { + void ::global_func(int) { } // expected-error{{definition or redeclaration of 'global_func' cannot name the global scope}} + + void f(); + // FIXME: if we move this to a separate definition of N, things break! +} +void ::global_func2(int) { } // expected-error{{definition or redeclaration of 'global_func2' cannot name the global scope}} + +void N::f() { } // okay + +struct Y; // expected-note{{forward declaration of 'struct Y'}} +Y::foo y; // expected-error{{incomplete type 'struct Y' named in nested name specifier}} \ + // expected-error{{unknown type name 'foo'}} + +X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \ + // expected-error{{C++ requires a type specifier for all declarations}} \ + // expected-error{{only constructors take base initializers}} diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp new file mode 100644 index 0000000..f890bf5 --- /dev/null +++ b/test/SemaCXX/new-delete.cpp @@ -0,0 +1,97 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stddef.h> + +struct S // expected-note {{candidate}} +{ + S(int, int, double); // expected-note {{candidate}} + S(double, int); // expected-note 2 {{candidate}} + S(float, int); // expected-note 2 {{candidate}} +}; +struct T; // expected-note{{forward declaration of 'struct T'}} +struct U +{ + // A special new, to verify that the global version isn't used. + void* operator new(size_t, S*); // expected-note {{candidate}} +}; +struct V : U +{ +}; + +void* operator new(size_t); // expected-note 2 {{candidate}} +void* operator new(size_t, int*); // expected-note 3 {{candidate}} +void* operator new(size_t, float*); // expected-note 3 {{candidate}} +void* operator new(size_t, S); // expected-note 2 {{candidate}} + +void good_news() +{ + int *pi = new int; + float *pf = new (pi) float(); + pi = new int(1); + pi = new int('c'); + const int *pci = new const int(); + S *ps = new S(1, 2, 3.4); + ps = new (pf) (S)(1, 2, 3.4); + S *(*paps)[2] = new S*[*pi][2]; + ps = new (S[3])(1, 2, 3.4); + typedef int ia4[4]; + ia4 *pai = new (int[3][4]); + pi = ::new int; + U *pu = new (ps) U; + // FIXME: Inherited functions are not looked up currently. + //V *pv = new (ps) V; + + pi = new (S(1.0f, 2)) int; +} + +struct abstract { + virtual ~abstract() = 0; +}; + +void bad_news(int *ip) +{ + int i = 1; + (void)new; // expected-error {{missing type specifier}} + (void)new 4; // expected-error {{missing type specifier}} + (void)new () int; // expected-error {{expected expression}} + (void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}} + (void)new int[1][i]; // expected-error {{only the first dimension}} + (void)new (int[1][i]); // expected-error {{only the first dimension}} + (void)new int(*(S*)0); // expected-error {{incompatible type initializing}} + (void)new int(1, 2); // expected-error {{initializer of a builtin type can only take one argument}} + (void)new S(1); // expected-error {{no matching constructor}} + (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}} + (void)new const int; // expected-error {{must provide an initializer}} + (void)new float*(ip); // expected-error {{incompatible type initializing 'int *', expected 'float *'}} + // Undefined, but clang should reject it directly. + (void)new int[-1]; // expected-error {{array size is negative}} + (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}} + (void)::S::new int; // expected-error {{expected unqualified-id}} + (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}} + (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}} + // This must fail, because the member version shouldn't be found. + (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}} + // This must fail, because any member version hides all global versions. + (void)new U; // expected-error {{no matching function for call to 'operator new'}} + (void)new (int[]); // expected-error {{array size must be specified in new expressions}} + (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}} + // Some lacking cases due to lack of sema support. +} + +void good_deletes() +{ + delete (int*)0; + delete [](int*)0; + delete (S*)0; + ::delete (int*)0; +} + +void bad_deletes() +{ + delete 0; // expected-error {{cannot delete expression of type 'int'}} + delete [0] (int*)0; // expected-error {{expected ']'}} \ + // expected-note {{to match this '['}} + delete (void*)0; // expected-error {{cannot delete expression}} + delete (T*)0; // expected-warning {{deleting pointer to incomplete type}} + ::S::delete (int*)0; // expected-error {{expected unqualified-id}} +} diff --git a/test/SemaCXX/no-implicit-builtin-decls.cpp b/test/SemaCXX/no-implicit-builtin-decls.cpp new file mode 100644 index 0000000..bd11f92 --- /dev/null +++ b/test/SemaCXX/no-implicit-builtin-decls.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() { + void *p = malloc(sizeof(int) * 10); // expected-error{{no matching function for call to 'malloc'}} +} + +int malloc(double); diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp new file mode 100644 index 0000000..6cc5a81 --- /dev/null +++ b/test/SemaCXX/nullptr.cpp @@ -0,0 +1,67 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s +#include <stdint.h> + +// Don't have decltype yet. +typedef __typeof__(nullptr) nullptr_t; + +struct A {}; + +int o1(char*); +void o1(uintptr_t); +void o2(char*); // expected-note {{candidate}} +void o2(int A::*); // expected-note {{candidate}} + +nullptr_t f(nullptr_t null) +{ + // Implicit conversions. + null = nullptr; + void *p = nullptr; + p = null; + int *pi = nullptr; + pi = null; + null = 0; + int A::*pm = nullptr; + pm = null; + void (*pf)() = nullptr; + pf = null; + void (A::*pmf)() = nullptr; + pmf = null; + bool b = nullptr; + + // Can't convert nullptr to integral implicitly. + uintptr_t i = nullptr; // expected-error {{incompatible type initializing}} + + // Operators + (void)(null == nullptr); + (void)(null <= nullptr); + (void)(null == (void*)0); + (void)((void*)0 == nullptr); + (void)(null <= (void*)0); + (void)((void*)0 <= nullptr); + (void)(1 > nullptr); // expected-error {{invalid operands to binary expression}} + (void)(1 != nullptr); // expected-error {{invalid operands to binary expression}} + (void)(1 + nullptr); // expected-error {{invalid operands to binary expression}} + (void)(0 ? nullptr : 0); // expected-error {{incompatible operand types}} + (void)(0 ? nullptr : (void*)0); + + // Overloading + int t = o1(nullptr); + t = o1(null); + o2(nullptr); // expected-error {{ambiguous}} + + // nullptr is an rvalue, null is an lvalue + (void)&nullptr; // expected-error {{address expression must be an lvalue}} + nullptr_t *pn = &null; + + // You can reinterpret_cast nullptr to an integer. + (void)reinterpret_cast<uintptr_t>(nullptr); + + // You can throw nullptr. + throw nullptr; +} + +// Template arguments can be nullptr. +template <int *PI, void (*PF)(), int A::*PM, void (A::*PMF)()> +struct T {}; + +typedef T<nullptr, nullptr, nullptr, nullptr> NT; diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp new file mode 100644 index 0000000..f0290e8 --- /dev/null +++ b/test/SemaCXX/offsetof.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s -Winvalid-offsetof + +struct NonPOD { + virtual void f(); + int m; +}; + +struct P { + NonPOD fieldThatPointsToANonPODType; +}; + +void f() { + int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-warning{{offset of on non-POD type 'struct P'}} +} + diff --git a/test/SemaCXX/overload-call-copycon.cpp b/test/SemaCXX/overload-call-copycon.cpp new file mode 100644 index 0000000..755e27a --- /dev/null +++ b/test/SemaCXX/overload-call-copycon.cpp @@ -0,0 +1,48 @@ +// RUN: clang-cc -fsyntax-only %s +class X { }; + +int& copycon(X x); +float& copycon(...); + +void test_copycon(X x, X const xc, X volatile xv) { + int& i1 = copycon(x); + int& i2 = copycon(xc); + float& f1 = copycon(xv); +} + +class A { +public: + A(A&); +}; + +class B : public A { }; + +short& copycon2(A a); +int& copycon2(B b); +float& copycon2(...); + +void test_copycon2(A a, const A ac, B b, B const bc, B volatile bv) { + int& i1 = copycon2(b); + float& f1 = copycon2(bc); + float& f2 = copycon2(bv); + short& s1 = copycon2(a); + float& f3 = copycon2(ac); +} + +int& copycon3(A a); +float& copycon3(...); + +void test_copycon3(B b, const B bc) { + int& i1 = copycon3(b); + float& f1 = copycon3(bc); +} + + +class C : public B { }; + +float& copycon4(A a); +int& copycon4(B b); + +void test_copycon4(C c) { + int& i = copycon4(c); +}; diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp new file mode 100644 index 0000000..94f352e --- /dev/null +++ b/test/SemaCXX/overload-call.cpp @@ -0,0 +1,280 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +int* f(int) { return 0; } +float* f(float) { return 0; } +void f(); + +void test_f(int iv, float fv) { + float* fp = f(fv); + int* ip = f(iv); +} + +int* g(int, float, int); // expected-note {{ candidate function }} +float* g(int, int, int); // expected-note {{ candidate function }} +double* g(int, float, float); // expected-note {{ candidate function }} +char* g(int, float, ...); // expected-note {{ candidate function }} +void g(); + +void test_g(int iv, float fv) { + int* ip1 = g(iv, fv, 0); + float* fp1 = g(iv, iv, 0); + double* dp1 = g(iv, fv, fv); + char* cp1 = g(0, 0); + char* cp2 = g(0, 0, 0, iv, fv); + + double* dp2 = g(0, fv, 1.5); // expected-error {{ call to 'g' is ambiguous; candidates are: }} +} + +double* h(double f); +int* h(int); + +void test_h(float fv, unsigned char cv) { + double* dp = h(fv); + int* ip = h(cv); +} + +int* i(int); +double* i(long); + +void test_i(short sv, int iv, long lv, unsigned char ucv) { + int* ip1 = i(sv); + int* ip2 = i(iv); + int* ip3 = i(ucv); + double* dp1 = i(lv); +} + +int* j(void*); +double* j(bool); + +void test_j(int* ip) { + int* ip1 = j(ip); +} + +int* k(char*); +double* k(bool); + +void test_k() { + int* ip1 = k("foo"); + double* dp1 = k(L"foo"); +} + +int* l(wchar_t*); +double* l(bool); + +void test_l() { + int* ip1 = l(L"foo"); + double* dp1 = l("foo"); +} + +int* m(const char*); +double* m(char*); + +void test_m() { + int* ip = m("foo"); +} + +int* n(char*); +double* n(void*); +class E; + +void test_n(E* e) { + char ca[7]; + int* ip1 = n(ca); + int* ip2 = n("foo"); + + float fa[7]; + double* dp1 = n(fa); + + double* dp2 = n(e); +} + +enum PromotesToInt { + PromotesToIntValue = -1 +}; + +enum PromotesToUnsignedInt { + PromotesToUnsignedIntValue = 1u +}; + +int* o(int); +double* o(unsigned int); +float* o(long); + +void test_o() { + int* ip1 = o(PromotesToIntValue); + double* dp1 = o(PromotesToUnsignedIntValue); +} + +int* p(int); +double* p(double); + +void test_p() { + int* ip = p((short)1); + double* dp = p(1.0f); +} + +struct Bits { + signed short int_bitfield : 5; + unsigned int uint_bitfield : 8; +}; + +int* bitfields(int, int); +float* bitfields(unsigned int, int); + +void test_bitfield(Bits bits, int x) { + int* ip = bitfields(bits.int_bitfield, 0); + float* fp = bitfields(bits.uint_bitfield, 0u); +} + +int* multiparm(long, int, long); // expected-note {{ candidate function }} +float* multiparm(int, int, int); // expected-note {{ candidate function }} +double* multiparm(int, int, short); // expected-note {{ candidate function }} + +void test_multiparm(long lv, short sv, int iv) { + int* ip1 = multiparm(lv, iv, lv); + int* ip2 = multiparm(lv, sv, lv); + float* fp1 = multiparm(iv, iv, iv); + float* fp2 = multiparm(sv, iv, iv); + double* dp1 = multiparm(sv, sv, sv); + double* dp2 = multiparm(iv, sv, sv); + multiparm(sv, sv, lv); // expected-error {{ call to 'multiparm' is ambiguous; candidates are: }} +} + +// Test overloading based on qualification vs. no qualification +// conversion. +int* quals1(int const * p); +char* quals1(int * p); + +int* quals2(int const * const * pp); +char* quals2(int * * pp); + +int* quals3(int const * * const * ppp); +char* quals3(int *** ppp); + +void test_quals(int * p, int * * pp, int * * * ppp) { + char* q1 = quals1(p); + char* q2 = quals2(pp); + char* q3 = quals3(ppp); +} + +// Test overloading based on qualification ranking (C++ 13.3.2)p3. +int* quals_rank1(int const * p); +float* quals_rank1(int const volatile *p); +char* quals_rank1(char*); +double* quals_rank1(const char*); + +int* quals_rank2(int const * const * pp); +float* quals_rank2(int * const * pp); + +void quals_rank3(int const * const * const volatile * p); // expected-note{{candidate function}} +void quals_rank3(int const * const volatile * const * p); // expected-note{{candidate function}} + +void quals_rank3(int const *); // expected-note{{candidate function}} +void quals_rank3(int volatile *); // expected-note{{candidate function}} + +void test_quals_ranking(int * p, int volatile *pq, int * * pp, int * * * ppp) { + int* q1 = quals_rank1(p); + float* q2 = quals_rank1(pq); + double* q3 = quals_rank1("string literal"); + char a[17]; + const char* ap = a; + char* q4 = quals_rank1(a); + double* q5 = quals_rank1(ap); + + float* q6 = quals_rank2(pp); + + quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}} + + quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}} + quals_rank3(pq); +} + +// Test overloading based on derived-to-base conversions +class A { }; +class B : public A { }; +class C : public B { }; +class D : public C { }; + +int* derived1(A*); +char* derived1(const A*); +float* derived1(void*); + +int* derived2(A*); +float* derived2(B*); + +int* derived3(A*); +float* derived3(const B*); +char* derived3(C*); + +void test_derived(B* b, B const* bc, C* c, const C* cc, void* v, D* d) { + int* d1 = derived1(b); + char* d2 = derived1(bc); + int* d3 = derived1(c); + char* d4 = derived1(cc); + float* d5 = derived1(v); + + float* d6 = derived2(b); + float* d7 = derived2(c); + + char* d8 = derived3(d); +} + +// Test overloading of references. +// (FIXME: tests binding to determine candidate sets, not overload +// resolution per se). +int* intref(int&); +float* intref(const int&); + +void intref_test() { + float* ir1 = intref(5); + float* ir2 = intref(5.5); +} + +// Test reference binding vs. standard conversions. +int& bind_vs_conv(const double&); +float& bind_vs_conv(int); + +void bind_vs_conv_test() +{ + int& i1 = bind_vs_conv(1.0f); + float& f1 = bind_vs_conv((short)1); +} + +// Test that cv-qualifiers get subsumed in the reference binding. +struct X { }; +struct Y { }; +struct Z : X, Y { }; + +int& cvqual_subsume(X&); // expected-note{{candidate function}} +float& cvqual_subsume(const Y&); // expected-note{{candidate function}} + +int& cvqual_subsume2(const X&); +float& cvqual_subsume2(const volatile Y&); + +Z get_Z(); + +void cvqual_subsume_test(Z z) { + cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous; candidates are:}} + int& x = cvqual_subsume2(get_Z()); // okay: only binds to the first one +} + +// Test overloading with cv-qualification differences in reference +// binding. +int& cvqual_diff(X&); +float& cvqual_diff(const X&); + +void cvqual_diff_test(X x, Z z) { + int& i1 = cvqual_diff(x); + int& i2 = cvqual_diff(z); +} + +// Test overloading with derived-to-base differences in reference +// binding. +struct Z2 : Z { }; + +int& db_rebind(X&); +long& db_rebind(Y&); +float& db_rebind(Z&); + +void db_rebind_test(Z2 z2) { + float& f1 = db_rebind(z2); +} diff --git a/test/SemaCXX/overload-decl.cpp b/test/SemaCXX/overload-decl.cpp new file mode 100644 index 0000000..2bc832f --- /dev/null +++ b/test/SemaCXX/overload-decl.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void f(); +void f(int); +void f(int, float); +void f(int, int); +void f(int, ...); + +typedef float Float; +void f(int, Float); // expected-note {{previous declaration is here}} + +int f(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +void g(void); // expected-note {{previous declaration is here}} +int g(); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +typedef int INT; + +class X { + void f(); + void f(int); // expected-note {{previous declaration is here}} + void f() const; + + void f(INT); // expected-error{{cannot be redeclared}} + + void g(int); // expected-note {{previous declaration is here}} + void g(int, float); // expected-note {{previous declaration is here}} + int g(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} + + static void g(float); + static void g(int); // expected-error {{static and non-static member functions with the same parameter types cannot be overloaded}} +}; diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp new file mode 100644 index 0000000..96e570d --- /dev/null +++ b/test/SemaCXX/overload-member-call.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct X { + int& f(int) const; // expected-note 2 {{candidate function}} + float& f(int); // expected-note 2 {{candidate function}} + + void test_f(int x) const { + int& i = f(x); + } + + void test_f2(int x) { + float& f2 = f(x); + } + + int& g(int) const; // expected-note 2 {{candidate function}} + float& g(int); // expected-note 2 {{candidate function}} + static double& g(double); // expected-note 2 {{candidate function}} + + void h(int); + + void test_member() { + float& f1 = f(0); + float& f2 = g(0); + double& d1 = g(0.0); + } + + void test_member_const() const { + int &i1 = f(0); + int &i2 = g(0); + double& d1 = g(0.0); + } + + static void test_member_static() { + double& d1 = g(0.0); + g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}} + } +}; + +void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp) { + int& i1 = xc.f(0); + int& i2 = xcp->f(0); + float& f1 = x.f(0); + float& f2 = xp->f(0); + xv.f(0); // expected-error{{no matching member function for call to 'f'; candidates are:}} + xvp->f(0); // expected-error{{no matching member function for call to 'f'; candidates are:}} + + int& i3 = xc.g(0); + int& i4 = xcp->g(0); + float& f3 = x.g(0); + float& f4 = xp->g(0); + double& d1 = xp->g(0.0); + double& d2 = X::g(0.0); + X::g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}} + + X::h(0); // expected-error{{call to non-static member function without an object argument}} +} diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp new file mode 100644 index 0000000..2a6c24a --- /dev/null +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -0,0 +1,122 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct yes; +struct no; + +struct Short { + operator short(); +}; + +struct Long { + operator long(); +}; + +enum E1 { }; +struct Enum1 { + operator E1(); +}; + +enum E2 { }; +struct Enum2 { + operator E2(); +}; + +yes& islong(long); +yes& islong(unsigned long); // FIXME: shouldn't be needed +no& islong(int); + +void f(Short s, Long l, Enum1 e1, Enum2 e2) { + // C++ [over.built]p8 + int i1 = +e1; + int i2 = -e2; + + // C++ [over.built]p10: + int i3 = ~s; + bool b1 = !s; + + // C++ [over.built]p12 + (void)static_cast<yes&>(islong(s + l)); + (void)static_cast<no&>(islong(s + s)); + + // C++ [over.built]p17 + (void)static_cast<yes&>(islong(s % l)); + (void)static_cast<yes&>(islong(l << s)); + (void)static_cast<no&>(islong(s << l)); + (void)static_cast<yes&>(islong(e1 % l)); + // FIXME: should pass (void)static_cast<no&>(islong(e1 % e2)); +} + +struct ShortRef { + operator short&(); +}; + +struct LongRef { + operator volatile long&(); +}; + +void g(ShortRef sr, LongRef lr) { + // C++ [over.built]p3 + short s1 = sr++; + + // C++ [over.built]p3 + long l1 = lr--; + + // C++ [over.built]p18 + short& sr1 = (sr *= lr); + volatile long& lr1 = (lr *= sr); + + // C++ [over.built]p22 + short& sr2 = (sr %= lr); + volatile long& lr2 = (lr <<= sr); + + bool b1 = (sr && lr) || (sr || lr); +} + +struct VolatileIntPtr { + operator int volatile *(); +}; + +struct ConstIntPtr { + operator int const *(); +}; + +struct VolatileIntPtrRef { + operator int volatile *&(); +}; + +struct ConstIntPtrRef { + operator int const *&(); +}; + +void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr, + VolatileIntPtrRef vipr, ConstIntPtrRef cipr) { + const int& cir1 = cip[sr]; + const int& cir2 = sr[cip]; + volatile int& vir1 = vip[sr]; + volatile int& vir2 = sr[vip]; + bool b1 = (vip == cip); + long p1 = vip - cip; + + // C++ [over.built]p5: + int volatile *vip1 = vipr++; + int const *cip1 = cipr++; + int volatile *&vipr1 = ++vipr; + int const *&cipr1 = --cipr; + + // C++ [over.built]p6: + int volatile &ivr = *vip; + + // C++ [over.built]p8: + int volatile *vip2 = +vip; + int i1 = +sr; + int i2 = -sr; + + // C++ [over.built]p13: + int volatile &ivr2 = vip[17]; + int const &icr2 = 17[cip]; +} + +// C++ [over.match.open]p4 + +void test_assign_restrictions(ShortRef& sr) { + sr = (short)0; // expected-error{{no viable overloaded '='}} +} diff --git a/test/SemaCXX/overloaded-operator-decl.cpp b/test/SemaCXX/overloaded-operator-decl.cpp new file mode 100644 index 0000000..fc17faf --- /dev/null +++ b/test/SemaCXX/overloaded-operator-decl.cpp @@ -0,0 +1,39 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + X(); + X(int); +}; + +X operator+(X, X); +X operator-(X, X) { X x; return x; } + +struct Y { + Y operator-() const; + void operator()(int x = 17) const; + int operator[](int); + + static int operator+(Y, Y); // expected-error{{overloaded 'operator+' cannot be a static member function}} +}; + + +void f(X x) { + x = operator+(x, x); +} + +X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} + +X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}} + +X operator/(X, X, ...); // expected-error{{overloaded 'operator/' cannot be variadic}} + +X operator%(Y); // expected-error{{overloaded 'operator%' must be a binary operator (has 1 parameter)}} + +void operator()(Y&, int, int); // expected-error{{overloaded 'operator()' must be a non-static member function}} + +typedef int INT; +typedef float FLOAT; +Y& operator++(Y&); +Y operator++(Y&, INT); +X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'FLOAT' (aka 'float'))}} + +int operator+; // expected-error{{'operator+' cannot be the name of a variable or data member}} diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp new file mode 100644 index 0000000..916d753 --- /dev/null +++ b/test/SemaCXX/overloaded-operator.cpp @@ -0,0 +1,211 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { }; + +X operator+(X, X); + +void f(X x) { + x = x + x; +} + +struct Y; +struct Z; + +struct Y { + Y(const Z&); +}; + +struct Z { + Z(const Y&); +}; + +Y operator+(Y, Y); +bool operator-(Y, Y); // expected-note{{candidate function}} +bool operator-(Z, Z); // expected-note{{candidate function}} + +void g(Y y, Z z) { + y = y + z; + bool b = y - z; // expected-error{{use of overloaded operator '-' is ambiguous; candidates are:}} +} + +struct A { + bool operator==(Z&); // expected-note{{candidate function}} +}; + +A make_A(); + +bool operator==(A&, Z&); // expected-note{{candidate function}} + +void h(A a, const A ac, Z z) { + make_A() == z; + a == z; // expected-error{{use of overloaded operator '==' is ambiguous; candidates are:}} + ac == z; // expected-error{{invalid operands to binary expression ('struct A const' and 'struct Z')}} +} + +struct B { + bool operator==(const B&) const; + + void test(Z z) { + make_A() == z; + } +}; + +enum Enum1 { }; +enum Enum2 { }; + +struct E1 { + E1(Enum1) { } +}; + +struct E2 { + E2(Enum2); +}; + +// C++ [over.match.oper]p3 - enum restriction. +float& operator==(E1, E2); + +void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2) { + float &f1 = (e1 == e2); + float &f2 = (enum1 == e2); + float &f3 = (e1 == enum2); + float &f4 = (enum1 == enum2); // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a temporary of type 'bool'}} +} + + +struct PostInc { + PostInc operator++(int); + PostInc& operator++(); +}; + +struct PostDec { + PostDec operator--(int); + PostDec& operator--(); +}; + +void incdec_test(PostInc pi, PostDec pd) { + const PostInc& pi1 = pi++; + const PostDec& pd1 = pd--; + PostInc &pi2 = ++pi; + PostDec &pd2 = --pd; +} + +struct SmartPtr { + int& operator*(); + long& operator*() const volatile; +}; + +void test_smartptr(SmartPtr ptr, const SmartPtr cptr, + const volatile SmartPtr cvptr) { + int &ir = *ptr; + long &lr = *cptr; + long &lr2 = *cvptr; +} + + +struct ArrayLike { + int& operator[](int); +}; + +void test_arraylike(ArrayLike a) { + int& ir = a[17]; +} + +struct SmartRef { + int* operator&(); +}; + +void test_smartref(SmartRef r) { + int* ip = &r; +} + +bool& operator,(X, Y); + +void test_comma(X x, Y y) { + bool& b1 = (x, y); + X& xr = (x, x); +} + +struct Callable { + int& operator()(int, double = 2.71828); // expected-note{{candidate function}} + float& operator()(int, double, long, ...); // expected-note{{candidate function}} + + double& operator()(float); // expected-note{{candidate function}} +}; + +struct Callable2 { + int& operator()(int i = 0); + double& operator()(...) const; +}; + +void test_callable(Callable c, Callable2 c2, const Callable2& c2c) { + int &ir = c(1); + float &fr = c(1, 3.14159, 17, 42); + + c(); // expected-error{{no matching function for call to object of type 'struct Callable'; candidates are:}} + + double &dr = c(1.0f); + + int &ir2 = c2(); + int &ir3 = c2(1); + double &fr2 = c2c(); +} + +typedef float FLOAT; +typedef int& INTREF; +typedef INTREF Func1(FLOAT, double); +typedef float& Func2(int, double); + +struct ConvertToFunc { + operator Func1*(); // expected-note{{conversion candidate of type 'INTREF (*)(FLOAT, double)'}} + operator Func2&(); // expected-note{{conversion candidate of type 'float &(&)(int, double)'}} + void operator()(); +}; + +void test_funcptr_call(ConvertToFunc ctf) { + int &i1 = ctf(1.0f, 2.0); + float &f2 = ctf((short int)1, 1.0f); + ctf((long int)17, 2.0); // expected-error{{error: call to object of type 'struct ConvertToFunc' is ambiguous; candidates are:}} + ctf(); +} + +struct HasMember { + int m; +}; + +struct Arrow1 { + HasMember* operator->(); +}; + +struct Arrow2 { + Arrow1 operator->(); // expected-note{{candidate function}} +}; + +void test_arrow(Arrow1 a1, Arrow2 a2, const Arrow2 a3) { + int &i1 = a1->m; + int &i2 = a2->m; + a3->m; // expected-error{{no viable overloaded 'operator->'; candidate is}} +} + +struct CopyConBase { +}; + +struct CopyCon : public CopyConBase { + CopyCon(const CopyConBase &Base); + + CopyCon(const CopyConBase *Base) { + *this = *Base; + } +}; + +namespace N { + struct X { }; +} + +namespace M { + N::X operator+(N::X, N::X); +} + +namespace M { + void test_X(N::X x) { + (void)(x + x); + } +} diff --git a/test/SemaCXX/qualification-conversion.cpp b/test/SemaCXX/qualification-conversion.cpp new file mode 100644 index 0000000..01e503d --- /dev/null +++ b/test/SemaCXX/qualification-conversion.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +int* quals1(int const * p); +int* quals2(int const * const * pp); +int* quals3(int const * * const * ppp); // expected-note{{candidate function}} + +void test_quals(int * p, int * * pp, int * * * ppp) { + int const * const * pp2 = pp; + quals1(p); + quals2(pp); + quals3(ppp); // expected-error {{no matching}} +} + +struct A {}; +void mquals1(int const A::*p); +void mquals2(int const A::* const A::*pp); +void mquals3(int const A::* A::* const A::*ppp); // expected-note{{candidate function}} + +void test_mquals(int A::*p, int A::* A::*pp, int A::* A::* A::*ppp) { + int const A::* const A::* pp2 = pp; + mquals1(p); + mquals2(pp); + mquals3(ppp); // expected-error {{no matching}} +} diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp new file mode 100644 index 0000000..254a18d --- /dev/null +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -0,0 +1,111 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace Ns { + int f(); // expected-note{{previous declaration is here}} + + enum E { + Enumerator + }; +} +namespace Ns { + double f(); // expected-error{{functions that differ only in their return type cannot be overloaded}} + + int x = Enumerator; +} + +namespace Ns2 { + float f(); +} + +int y = Ns::Enumerator; + +namespace Ns2 { + float f(int); // expected-note{{previous declaration is here}} +} + +namespace Ns2 { + double f(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} +} + +namespace N { + int& f1(); +} + +namespace N { + struct f1 { + static int member; + + typedef int type; + + void foo(type); + }; + + void test_f1() { + int &i1 = f1(); + } +} + +void N::f1::foo(int i) { + f1::member = i; + f1::type &ir = i; +} + +namespace N { + float& f1(int x) { + N::f1::type& i1 = x; + f1::type& i2 = x; + } + + struct f2 { + static int member; + }; + void f2(); +} + +int i1 = N::f1::member; +typedef struct N::f1 type1; +int i2 = N::f2::member; +typedef struct N::f2 type2; + +void test_f1(int i) { + int &v1 = N::f1(); + float &v2 = N::f1(i); + int v3 = ::i1; + int v4 = N::f1::member; +} + +typedef int f2_type; +namespace a { + typedef int f2_type(int, int); + + void test_f2() { + ::f2_type(1, 2); // expected-error {{function-style cast to a builtin type can only take one argument}} + } +} + +// PR clang/3291 +namespace a { + namespace a { // A1 + namespace a { // A2 + int i; + } + } +} + +void test_a() { + a::a::i = 3; // expected-error{{no member named 'i'}} + a::a::a::i = 4; +} + +struct Undef { // expected-note{{definition of 'struct Undef' is not complete until the closing '}'}} + typedef int type; + + Undef::type member; + + static int size = sizeof(Undef); // expected-error{{invalid application of 'sizeof' to an incomplete type 'struct Undef'}} + + int f(); +}; + +int Undef::f() { + return sizeof(Undef); +} diff --git a/test/SemaCXX/qualified-names-diag.cpp b/test/SemaCXX/qualified-names-diag.cpp new file mode 100644 index 0000000..3bffd7c --- /dev/null +++ b/test/SemaCXX/qualified-names-diag.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace foo { + namespace wibble { + struct x { int y; }; + + namespace bar { + namespace wonka { + struct x { + struct y { }; + }; + } + } + } +} + +namespace bar { + typedef int y; + + struct incomplete; // expected-note{{forward declaration of 'struct bar::incomplete'}} +} +void test() { + foo::wibble::x a; + ::bar::y b; + a + b; // expected-error{{invalid operands to binary expression ('foo::wibble::x' and '::bar::y' (aka 'int'))}} + + ::foo::wibble::bar::wonka::x::y c; + c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' and '::bar::y' (aka 'int'))}} + + (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete'}} +} + +int ::foo::wibble::bar::wonka::x::y::* ptrmem; + diff --git a/test/SemaCXX/qualified-names-print.cpp b/test/SemaCXX/qualified-names-print.cpp new file mode 100644 index 0000000..1cb19f0 --- /dev/null +++ b/test/SemaCXX/qualified-names-print.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -ast-print %s 2>&1 | grep "N::M::X<INT>::value" +namespace N { + namespace M { + template<typename T> + struct X { + enum { value }; + }; + } +} + +typedef int INT; + +int test() { + return N::M::X<INT>::value; +} diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp new file mode 100644 index 0000000..9067a86 --- /dev/null +++ b/test/SemaCXX/references.cpp @@ -0,0 +1,89 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int g(int); + +void f() { + int i; + int &r = i; + r = 1; + int *p = &r; + int &rr = r; + int (&rg)(int) = g; + rg(i); + int a[3]; + int (&ra)[3] = a; + ra[1] = i; + int *Q; + int *& P = Q; + P[1] = 1; +} + +typedef int t[1]; +void test2() { + t a; + t& b = a; + + + int c[3]; + int (&rc)[3] = c; +} + +// C++ [dcl.init.ref]p5b1 +struct A { }; +struct B : A { } b; + +void test3() { + double d = 2.0; + double& rd = d; // rd refers to d + const double& rcd = d; // rcd refers to d + + A& ra = b; // ra refers to A subobject in b + const A& rca = b; // rca refers to A subobject in b +} + +B fB(); + +// C++ [dcl.init.ref]p5b2 +void test4() { + double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a temporary of type 'double'}} + int i = 2; + double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a value of type 'int'}} + + const A& rca = fB(); +} + +void test5() { + const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 + const volatile int cvi = 1; + const int& r = cvi; // expected-error{{initialization of reference to type 'int const' with a value of type 'int const volatile' drops qualifiers}} +} + +// C++ [dcl.init.ref]p3 +int& test6(int& x) { + int& yo; // expected-error{{declaration of reference variable 'yo' requires an initializer}} + + return x; +} +int& not_initialized_error; // expected-error{{declaration of reference variable 'not_initialized_error' requires an initializer}} +extern int& not_initialized_okay; + +class Test6 { + int& okay; +}; + +struct C : B, A { }; + +void test7(C& c) { + A& a1 = c; // expected-error {{ambiguous conversion from derived class 'struct C' to base class 'struct A':}} +} + +// C++ [dcl.ref]p1, C++ [dcl.ref]p4 +void test8(int& const,// expected-error{{'const' qualifier may not be applied to a reference}} + + void&, // expected-error{{cannot form a reference to 'void'}} + int& &) // expected-error{{type name declared as a reference to a reference}} +{ + typedef int& intref; + typedef intref& intrefref; // C++ DR 106: reference collapsing + + typedef intref const intref_c; // okay. FIXME: how do we verify that this is the same type as intref? +} diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp new file mode 100644 index 0000000..fd5ca8c --- /dev/null +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -0,0 +1,90 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +enum test { testval = 1 }; +struct structure { int m; }; +typedef void (*fnptr)(); + +// Test the conversion to self. +void self_conversion() +{ + // T*->T* is allowed, T->T in general not. + int i = 0; + (void)reinterpret_cast<int>(i); // expected-error {{reinterpret_cast from 'int' to 'int' is not allowed}} + structure s; + (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'struct structure' to 'struct structure' is not allowed}} + int *pi = 0; + (void)reinterpret_cast<int*>(pi); +} + +// Test conversion between pointer and integral types, as in /3 and /4. +void integral_conversion() +{ + void *vp = reinterpret_cast<void*>(testval); + long l = reinterpret_cast<long>(vp); + (void)reinterpret_cast<float*>(l); + fnptr fnp = reinterpret_cast<fnptr>(l); + (void)reinterpret_cast<char>(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}} + (void)reinterpret_cast<long>(fnp); +} + +void pointer_conversion() +{ + int *p1 = 0; + float *p2 = reinterpret_cast<float*>(p1); + structure *p3 = reinterpret_cast<structure*>(p2); + typedef int **ppint; + ppint *deep = reinterpret_cast<ppint*>(p3); + (void)reinterpret_cast<fnptr*>(deep); +} + +void constness() +{ + int ***const ipppc = 0; + // Valid: T1* -> T2 const* + int const *icp = reinterpret_cast<int const*>(ipppc); + // Invalid: T1 const* -> T2* + (void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'int const *' to 'int *' casts away constness}} + // Invalid: T1*** -> T2 const* const** + int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***const' to 'int const *const **' casts away constness}} + // Valid: T1* -> T2* + int *ip = reinterpret_cast<int*>(icpcpp); + // Valid: T* -> T const* + (void)reinterpret_cast<int const*>(ip); + // Valid: T*** -> T2 const* const* const* + (void)reinterpret_cast<int const* const* const*>(ipppc); +} + +void fnptrs() +{ + typedef int (*fnptr2)(int); + fnptr fp = 0; + (void)reinterpret_cast<fnptr2>(fp); + void *vp = reinterpret_cast<void*>(fp); + (void)reinterpret_cast<fnptr>(vp); +} + +void refs() +{ + long l = 0; + char &c = reinterpret_cast<char&>(l); + // Bad: from rvalue + (void)reinterpret_cast<int&>(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}} +} + +void memptrs() +{ + const int structure::*psi = 0; + (void)reinterpret_cast<const float structure::*>(psi); + (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'int struct structure::*' casts away constness}} + + void (structure::*psf)() = 0; + (void)reinterpret_cast<int (structure::*)()>(psf); + + (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'void (struct structure::*)(void)' is not allowed}} + (void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (struct structure::*)(void)' to 'int struct structure::*' is not allowed}} + + // Cannot cast from integers to member pointers, not even the null pointer + // literal. + (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)(void)' is not allowed}} + (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}} +} diff --git a/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp new file mode 100644 index 0000000..16b8659 --- /dev/null +++ b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 -pedantic %s + +void fnptrs() +{ + typedef void (*fnptr)(); + fnptr fp = 0; + void *vp = reinterpret_cast<void*>(fp); // expected-warning {{reinterpret_cast between pointer-to-function and pointer-to-object is an extension}} + (void)reinterpret_cast<fnptr>(vp); // expected-warning {{reinterpret_cast between pointer-to-function and pointer-to-object is an extension}} +} diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp new file mode 100644 index 0000000..457de29 --- /dev/null +++ b/test/SemaCXX/return-stack-addr.cpp @@ -0,0 +1,112 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int* ret_local() { + int x = 1; + return &x; // expected-warning {{address of stack memory}} +} + +int* ret_local_array() { + int x[10]; + return x; // expected-warning {{address of stack memory}} +} + +int* ret_local_array_element(int i) { + int x[10]; + return &x[i]; // expected-warning {{address of stack memory}} +} + +int *ret_local_array_element_reversed(int i) { + int x[10]; + return &i[x]; // expected-warning {{address of stack memory}} +} + +int* ret_local_array_element_const_index() { + int x[10]; + return &x[2]; // expected-warning {{address of stack memory}} +} + +int& ret_local_ref() { + int x = 1; + return x; // expected-warning {{reference to stack memory}} +} + +int* ret_local_addrOf() { + int x = 1; + return &*&x; // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_paren() { + int x = 1; + return (&(*(&x))); // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_ptr_arith() { + int x = 1; + return &*(&x+1); // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_ptr_arith2() { + int x = 1; + return &*(&x+1); // expected-warning {{address of stack memory}} +} + +int* ret_local_field() { + struct { int x; } a; + return &a.x; // expected-warning {{address of stack memory}} +} + +int& ret_local_field_ref() { + struct { int x; } a; + return a.x; // expected-warning {{reference to stack memory}} +} + +int* ret_conditional(bool cond) { + int x = 1; + int y = 2; + return cond ? &x : &y; // expected-warning {{address of stack memory}} +} + +int* ret_conditional_rhs(int *x, bool cond) { + int y = 1; + return cond ? x : &y; // expected-warning {{address of stack memory}} +} + +void* ret_c_cast() { + int x = 1; + return (void*) &x; // expected-warning {{address of stack memory}} +} + +int* ret_static_var() { + static int x = 1; + return &x; // no warning. +} + +int z = 1; + +int* ret_global() { + return &z; // no warning. +} + +int* ret_parameter(int x) { + return &x; // expected-warning {{address of stack memory}} +} + + +void* ret_cpp_static_cast(short x) { + return static_cast<void*>(&x); // expected-warning {{address of stack memory}} +} + +int* ret_cpp_reinterpret_cast(double x) { + return reinterpret_cast<int*>(&x); // expected-warning {{address of stack me}} +} + +int* ret_cpp_reinterpret_cast_no_warning(long x) { + return reinterpret_cast<int*>(x); // no-warning +} + +int* ret_cpp_const_cast(const int x) { + return const_cast<int*>(&x); // expected-warning {{address of stack memory}} +} + +// TODO: test case for dynamic_cast. clang does not yet have +// support for C++ classes to write such a test case. diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp new file mode 100644 index 0000000..a7d26bb --- /dev/null +++ b/test/SemaCXX/rval-references.cpp @@ -0,0 +1,91 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +typedef int&& irr; +typedef irr& ilr_c1; // Collapses to int& +typedef int& ilr; +typedef ilr&& ilr_c2; // Collapses to int& + +irr ret_irr() { + return 0; +} + +struct not_int {}; + +int over(int&); +not_int over(int&&); + +int over2(const int&); +not_int over2(int&&); + +struct conv_to_not_int_rvalue { + operator not_int &&(); +}; + +void f() { + int &&virr1; // expected-error {{declaration of reference variable 'virr1' requires an initializer}} + int &&virr2 = 0; + int &&virr3 = virr2; // expected-error {{rvalue reference cannot bind to lvalue}} + int i1 = 0; + int &&virr4 = i1; // expected-error {{rvalue reference cannot bind to lvalue}} + int &&virr5 = ret_irr(); + int &&virr6 = static_cast<int&&>(i1); + (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}} + + int i2 = over(i1); + not_int ni1 = over(0); + int i3 = over(virr2); + not_int ni2 = over(ret_irr()); + + int i4 = over2(i1); + not_int ni3 = over2(0); + + ilr_c1 vilr1 = i1; + ilr_c2 vilr2 = i1; + + conv_to_not_int_rvalue cnir; + not_int &&ni4 = cnir; // expected-error {{rvalue reference cannot bind to lvalue}} + not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot be initialized with a value of type 'struct conv_to_not_int_rvalue'}} + not_int &&ni6 = conv_to_not_int_rvalue(); + + + try { + } catch(int&&) { // expected-error {{cannot catch exceptions by rvalue reference}} + } +} + +int&& should_warn(int i) { + // FIXME: The stack address return test doesn't reason about casts. + return static_cast<int&&>(i); // xpected-warning {{returning reference to temporary}} +} +int&& should_not_warn(int&& i) { // But GCC 4.4 does + return static_cast<int&&>(i); +} + + +// Test the return dance. This also tests IsReturnCopyElidable. +struct MoveOnly { + MoveOnly(); + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&); + MoveOnly(int&&); +}; + +MoveOnly returning() { + MoveOnly mo; + return mo; +} + +MoveOnly gmo; +MoveOnly returningNonEligible() { + int i; + static MoveOnly mo; + MoveOnly &r = mo; + if (0) // Copy from global can't be elided + return gmo; // expected-error {{incompatible type returning}} + else if (0) // Copy from local static can't be elided + return mo; // expected-error {{incompatible type returning}} + else if (0) // Copy from reference can't be elided + return r; // expected-error {{incompatible type returning}} + else // Construction from different type can't be elided + return i; // expected-error {{incompatible type returning}} +} diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp new file mode 100644 index 0000000..d6925fe --- /dev/null +++ b/test/SemaCXX/statements.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -fsyntax-only -pedantic + +void foo() { + return foo(); +} diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp new file mode 100644 index 0000000..caf7603 --- /dev/null +++ b/test/SemaCXX/static-assert.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +int f(); + +static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}} +static_assert(true, "true is not false"); +static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} + +void g() { + static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} +} + +class C { + static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} +}; + +template<int N> struct T { + static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}} +}; + +T<1> t1; // expected-note {{in instantiation of template class 'struct T<1>' requested here}} +T<2> t2; + +template<typename T> struct S { + static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}} +}; + +S<char> s1; // expected-note {{in instantiation of template class 'struct S<char>' requested here}} +S<int> s2; + diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp new file mode 100644 index 0000000..8399e77 --- /dev/null +++ b/test/SemaCXX/static-cast.cpp @@ -0,0 +1,129 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; +struct B : public A {}; // Single public base. +struct C1 : public virtual B {}; // Single virtual base. +struct C2 : public virtual B {}; +struct D : public C1, public C2 {}; // Diamond +struct E : private A {}; // Single private base. +struct F : public C1 {}; // Single path to B with virtual. +struct G1 : public B {}; +struct G2 : public B {}; +struct H : public G1, public G2 {}; // Ambiguous path to B. + +enum Enum { En1, En2 }; +enum Onom { On1, On2 }; + +// Explicit implicits +void t_529_2() +{ + int i = 1; + (void)static_cast<float>(i); + double d = 1.0; + (void)static_cast<float>(d); + (void)static_cast<int>(d); + (void)static_cast<char>(i); + (void)static_cast<unsigned long>(i); + (void)static_cast<int>(En1); + (void)static_cast<double>(En1); + (void)static_cast<int&>(i); + (void)static_cast<const int&>(i); + + int ar[1]; + (void)static_cast<const int*>(ar); + (void)static_cast<void (*)()>(t_529_2); + + (void)static_cast<void*>(0); + (void)static_cast<void*>((int*)0); + (void)static_cast<volatile const void*>((const int*)0); + (void)static_cast<A*>((B*)0); + (void)static_cast<A&>(*((B*)0)); + (void)static_cast<const B*>((C1*)0); + (void)static_cast<B&>(*((C1*)0)); + (void)static_cast<A*>((D*)0); + (void)static_cast<const A&>(*((D*)0)); + (void)static_cast<int B::*>((int A::*)0); + (void)static_cast<void (B::*)()>((void (A::*)())0); + + // TODO: User-defined conversions + + // Bad code below + + (void)static_cast<void*>((const int*)0); // expected-error {{static_cast from 'int const *' to 'void *' is not allowed}} + //(void)static_cast<A*>((E*)0); // {{static_cast from 'struct E *' to 'struct A *' is not allowed}} + //(void)static_cast<A*>((H*)0); // {{static_cast from 'struct H *' to 'struct A *' is not allowed}} + (void)static_cast<int>((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}} + (void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'struct B **' to 'struct A **' is not allowed}} + (void)static_cast<char&>(i); // expected-error {{non-const lvalue reference to type 'char' cannot be initialized with a value of type 'int'}} +} + +// Anything to void +void t_529_4() +{ + static_cast<void>(1); + static_cast<void>(t_529_4); +} + +// Static downcasts +void t_529_5_8() +{ + (void)static_cast<B*>((A*)0); + (void)static_cast<B&>(*((A*)0)); + (void)static_cast<const G1*>((A*)0); + (void)static_cast<const G1&>(*((A*)0)); + + // Bad code below + + (void)static_cast<C1*>((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct C1 *' via virtual base 'struct B'}} + (void)static_cast<C1&>(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct C1 &' via virtual base 'struct B'}} + (void)static_cast<D*>((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct D *' via virtual base 'struct B'}} + (void)static_cast<D&>(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct D &' via virtual base 'struct B'}} + (void)static_cast<B*>((const A*)0); // expected-error {{static_cast from 'struct A const *' to 'struct B *' casts away constness}} + (void)static_cast<B&>(*((const A*)0)); // expected-error {{static_cast from 'struct A const' to 'struct B &' casts away constness}} + // Accessibility is not yet tested + //(void)static_cast<E*>((A*)0); // {{static_cast from 'struct A *' to 'struct E *' is not allowed}} + //(void)static_cast<E&>(*((A*)0)); // {{static_cast from 'struct A' to 'struct E &' is not allowed}} + (void)static_cast<H*>((A*)0); // expected-error {{ambiguous static_cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous static_cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'struct B *' to 'struct E *' is not allowed}} + (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'struct E' cannot be initialized with a value of type 'struct B'}} + + // TODO: Test inaccessible base in context where it's accessible, i.e. + // member function and friend. + + // TODO: Test DR427. This requires user-defined conversions, though. +} + +// Enum conversions +void t_529_7() +{ + (void)static_cast<Enum>(1); + (void)static_cast<Enum>(1.0); + (void)static_cast<Onom>(En1); + + // Bad code below + + (void)static_cast<Enum>((int*)0); // expected-error {{static_cast from 'int *' to 'enum Enum' is not allowed}} +} + +// Void pointer to object pointer +void t_529_10() +{ + (void)static_cast<int*>((void*)0); + (void)static_cast<const A*>((void*)0); + + // Bad code below + + (void)static_cast<int*>((const void*)0); // expected-error {{static_cast from 'void const *' to 'int *' casts away constness}} + (void)static_cast<void (*)()>((void*)0); // expected-error {{static_cast from 'void *' to 'void (*)(void)' is not allowed}} +} + +// Member pointer upcast. +void t_529_9() +{ + (void)static_cast<int A::*>((int B::*)0); + + // Bad code below + (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'struct H'}} + (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'struct F'}} +} diff --git a/test/SemaCXX/static-initializers.cpp b/test/SemaCXX/static-initializers.cpp new file mode 100644 index 0000000..3d92a53 --- /dev/null +++ b/test/SemaCXX/static-initializers.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int f() +{ + return 10; +} + +void g() +{ + static int a = f(); +} + +static int b = f(); diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp new file mode 100644 index 0000000..4b6cef6 --- /dev/null +++ b/test/SemaCXX/struct-class-redecl.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -Wmismatched-tags -verify %s +class X; // expected-note 2{{here}} +typedef struct X * X_t; // expected-warning{{previously declared}} + +template<typename T> struct Y; // expected-note{{previous}} +template<class U> class Y { }; // expected-warning{{previously declared}} + +union X { int x; float y; }; // expected-error{{use of 'X' with tag type that does not match previous declaration}} diff --git a/test/SemaCXX/template-specialization.cpp b/test/SemaCXX/template-specialization.cpp new file mode 100644 index 0000000..b3bb08d --- /dev/null +++ b/test/SemaCXX/template-specialization.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<int N> void f(int (&array)[N]); + +template<> void f<1>(int (&array)[1]) { } diff --git a/test/SemaCXX/this.cpp b/test/SemaCXX/this.cpp new file mode 100644 index 0000000..0577d3c --- /dev/null +++ b/test/SemaCXX/this.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} + +void f() { + int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} +} diff --git a/test/SemaCXX/trivial-constructor.cpp b/test/SemaCXX/trivial-constructor.cpp new file mode 100644 index 0000000..8fc14d9 --- /dev/null +++ b/test/SemaCXX/trivial-constructor.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x +struct T1 { +}; +static_assert(__has_trivial_constructor(T1), "T1 has trivial constructor!"); + +struct T2 { + T2(); +}; +static_assert(!__has_trivial_constructor(T2), "T2 has a user-declared constructor!"); + +struct T3 { + virtual void f(); +}; +static_assert(!__has_trivial_constructor(T3), "T3 has a virtual function!"); + +struct T4 : virtual T3 { +}; +static_assert(!__has_trivial_constructor(T4), "T4 has a virtual base class!"); + +struct T5 : T1 { +}; +static_assert(__has_trivial_constructor(T5), "All the direct base classes of T5 have trivial constructors!"); + +struct T6 { + T5 t5; + T1 t1[2][2]; + static T2 t2; +}; +static_assert(__has_trivial_constructor(T6), "All nonstatic data members of T6 have trivial constructors!"); + +struct T7 { + T4 t4; +}; +static_assert(!__has_trivial_constructor(T7), "t4 does not have a trivial constructor!"); + +struct T8 : T2 { +}; +static_assert(!__has_trivial_constructor(T8), "The base class T2 does not have a trivial constructor!"); diff --git a/test/SemaCXX/trivial-destructor.cpp b/test/SemaCXX/trivial-destructor.cpp new file mode 100644 index 0000000..9e7f3a1 --- /dev/null +++ b/test/SemaCXX/trivial-destructor.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x +struct T1 { +}; +static_assert(__has_trivial_destructor(T1), "T1 has trivial destructor!"); + +struct T2 { + ~T2(); +}; +static_assert(!__has_trivial_destructor(T2), "T2 has a user-declared destructor!"); + +struct T3 { + virtual void f(); +}; +static_assert(__has_trivial_destructor(T3), "T3 has a virtual function (but still a trivial destructor)!"); + +struct T4 : virtual T3 { +}; +static_assert(__has_trivial_destructor(T4), "T4 has a virtual base class! (but still a trivial destructor)!"); + +struct T5 : T1 { +}; +static_assert(__has_trivial_destructor(T5), "All the direct base classes of T5 have trivial destructors!"); + +struct T6 { + T5 t5; + T1 t1[2][2]; + static T2 t2; +}; +static_assert(__has_trivial_destructor(T6), "All nonstatic data members of T6 have trivial destructors!"); + +struct T7 { + T2 t2; +}; +static_assert(!__has_trivial_destructor(T7), "t2 does not have a trivial destructor!"); + +struct T8 : T2 { +}; +static_assert(!__has_trivial_destructor(T8), "The base class T2 does not have a trivial destructor!"); diff --git a/test/SemaCXX/type-convert-construct.cpp b/test/SemaCXX/type-convert-construct.cpp new file mode 100644 index 0000000..1840456 --- /dev/null +++ b/test/SemaCXX/type-convert-construct.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() { + float v1 = float(1); + int v2 = typeof(int)(1,2); // expected-error {{function-style cast to a builtin type can only take one argument}} + typedef int arr[]; + int v3 = arr(); // expected-error {{array types cannot be value-initialized}} + int v4 = int(); + int v5 = int; // expected-error {{expected '(' for function-style cast or type construction}} + typedef int T; + int *p; + bool v6 = T(0) == p; + char *str; + str = "a string"; + wchar_t *wstr; + wstr = L"a wide string"; +} diff --git a/test/SemaCXX/type-definition-in-specifier.cpp b/test/SemaCXX/type-definition-in-specifier.cpp new file mode 100644 index 0000000..60c28b0 --- /dev/null +++ b/test/SemaCXX/type-definition-in-specifier.cpp @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct S0; +struct S1; +struct S2; +struct S3; +struct S4; +struct S5; +struct S6; + +struct S0 { int x; }; + +void f0() { + typedef struct S1 { int x; } S1_typedef; + + (void)((struct S2 { int x; }*)0); // expected-error{{can not be defined}} + + struct S3 { int x; } s3; + + (void)static_cast<struct S4 { int x; } *>(0); // expected-error{{can not be defined}} +} + +struct S5 { int x; } f1() { return S5(); } // expected-error{{result type}} + +void f2(struct S6 { int x; } p); // expected-error{{parameter type}} diff --git a/test/SemaCXX/type-dependent-exprs.cpp b/test/SemaCXX/type-dependent-exprs.cpp new file mode 100644 index 0000000..dd31ef0 --- /dev/null +++ b/test/SemaCXX/type-dependent-exprs.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { +public: + virtual int f(); +}; + +void g(int); // expected-note{{candidate function}} + +template<typename T> +T f(T x) { + (void)(x + 0); + (void)T(0); + (void)(x += 0); + (void)(x? x : x); + (void)static_cast<int>(x); + (void)reinterpret_cast<int>(x); + (void)dynamic_cast<X*>(&x); + (void)const_cast<int>(x); + return g(x); + h(x); // h is a dependent name + g(1, 1); // expected-error{{no matching function for call}} + h(1); // expected-error{{no matching function for call to 'h'}} + return 0; +} diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp new file mode 100644 index 0000000..1a2e329 --- /dev/null +++ b/test/SemaCXX/type-traits.cpp @@ -0,0 +1,111 @@ +// RUN: clang-cc -fsyntax-only -verify %s +#define T(b) (b) ? 1 : -1 +#define F(b) (b) ? -1 : 1 + +struct NonPOD { NonPOD(int); }; + +// PODs +enum Enum { EV }; +struct POD { Enum e; int i; float f; NonPOD* p; }; +typedef int Int; +typedef Int IntAr[10]; +class Statics { static int priv; static NonPOD np; }; + +// Not PODs +struct Derives : POD {}; +struct HasCons { HasCons(int); }; +struct HasAssign { HasAssign operator =(const HasAssign&); }; +struct HasDest { ~HasDest(); }; +class HasPriv { int priv; }; +class HasProt { protected: int prot; }; +struct HasRef { int i; int& ref; HasRef() : i(0), ref(i) {} }; +struct HasNonPOD { NonPOD np; }; +struct HasVirt { virtual void Virt() {}; }; +typedef Derives NonPODAr[10]; + +void is_pod() +{ + int t01[T(__is_pod(int))]; + int t02[T(__is_pod(Enum))]; + int t03[T(__is_pod(POD))]; + int t04[T(__is_pod(Int))]; + int t05[T(__is_pod(IntAr))]; + int t06[T(__is_pod(Statics))]; + + int t21[F(__is_pod(Derives))]; + int t22[F(__is_pod(HasCons))]; + int t23[F(__is_pod(HasAssign))]; + int t24[F(__is_pod(HasDest))]; + int t25[F(__is_pod(HasPriv))]; + int t26[F(__is_pod(HasProt))]; + int t27[F(__is_pod(HasRef))]; + int t28[F(__is_pod(HasNonPOD))]; + int t29[F(__is_pod(HasVirt))]; + int t30[F(__is_pod(NonPODAr))]; +} + +union Union { int i; float f; }; +typedef Derives ClassType; + +void is_class() +{ + int t01[T(__is_class(Derives))]; + int t02[T(__is_class(HasPriv))]; + int t03[T(__is_class(ClassType))]; + + int t11[F(__is_class(int))]; + int t12[F(__is_class(Enum))]; + int t13[F(__is_class(Int))]; + int t14[F(__is_class(IntAr))]; + int t15[F(__is_class(NonPODAr))]; + int t16[F(__is_class(Union))]; +} + +typedef Union UnionAr[10]; +typedef Union UnionType; + +void is_union() +{ + int t01[T(__is_union(Union))]; + int t02[T(__is_union(UnionType))]; + + int t11[F(__is_union(int))]; + int t12[F(__is_union(Enum))]; + int t13[F(__is_union(Int))]; + int t14[F(__is_union(IntAr))]; + int t15[F(__is_union(UnionAr))]; +} + +typedef Enum EnumType; + +void is_enum() +{ + int t01[T(__is_enum(Enum))]; + int t02[T(__is_enum(EnumType))]; + + int t11[F(__is_enum(int))]; + int t12[F(__is_enum(Union))]; + int t13[F(__is_enum(Int))]; + int t14[F(__is_enum(IntAr))]; + int t15[F(__is_enum(UnionAr))]; + int t16[F(__is_enum(Derives))]; + int t17[F(__is_enum(ClassType))]; +} + +struct Polymorph { virtual void f(); }; +struct InheritPolymorph : Polymorph {}; + +void is_polymorphic() +{ + int t01[T(__is_polymorphic(Polymorph))]; + int t02[T(__is_polymorphic(InheritPolymorph))]; + + int t11[F(__is_polymorphic(int))]; + int t12[F(__is_polymorphic(Union))]; + int t13[F(__is_polymorphic(Int))]; + int t14[F(__is_polymorphic(IntAr))]; + int t15[F(__is_polymorphic(UnionAr))]; + int t16[F(__is_polymorphic(Derives))]; + int t17[F(__is_polymorphic(ClassType))]; + int t18[F(__is_polymorphic(Enum))]; +} diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp new file mode 100644 index 0000000..e38f474 --- /dev/null +++ b/test/SemaCXX/typedef-redecl.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef int INT; +typedef INT REALLY_INT; // expected-note {{previous definition is here}} +typedef REALLY_INT REALLY_REALLY_INT; +typedef REALLY_INT BOB; +typedef float REALLY_INT; // expected-error{{typedef redefinition with different types ('float' vs 'INT' (aka 'int'))}} + +struct X { + typedef int result_type; // expected-note {{previous definition is here}} + typedef INT result_type; // expected-error {{redefinition of 'result_type'}} +}; + +struct Y; // expected-note{{previous definition is here}} +typedef int Y; // expected-error{{typedef redefinition with different types ('int' vs 'struct Y')}} + +typedef int Y2; // expected-note{{previous definition is here}} +struct Y2; // expected-error{{definition of type 'struct Y2' conflicts with typedef of the same name}} + +void f(); // expected-note{{previous definition is here}} +typedef int f; // expected-error{{redefinition of 'f' as different kind of symbol}} + +typedef int f2; // expected-note{{previous definition is here}} +void f2(); // expected-error{{redefinition of 'f2' as different kind of symbol}} + +typedef struct s s; +typedef int I; +typedef int I; +typedef I I; + +struct s { }; + diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp new file mode 100644 index 0000000..f9ad759 --- /dev/null +++ b/test/SemaCXX/typeid.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() +{ + (void)typeid(int); // expected-error {{error: you need to include <typeinfo> before using the 'typeid' operator}} +} + +// FIXME: This should really include <typeinfo>, but we don't have that yet. +namespace std { + class type_info; +} + +void g() +{ + (void)typeid(int); +} diff --git a/test/SemaCXX/types_compatible_p.cpp b/test/SemaCXX/types_compatible_p.cpp new file mode 100644 index 0000000..30b1600 --- /dev/null +++ b/test/SemaCXX/types_compatible_p.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +bool f() { + return __builtin_types_compatible_p(int, const int); // expected-error{{C++}} +} diff --git a/test/SemaCXX/unused.cpp b/test/SemaCXX/unused.cpp new file mode 100644 index 0000000..55f959d --- /dev/null +++ b/test/SemaCXX/unused.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR4103 : Make sure we don't get a bogus unused expression warning +class APInt { + char foo; +}; +class APSInt : public APInt { + char bar; +public: + APSInt &operator=(const APSInt &RHS); +}; + +APSInt& APSInt::operator=(const APSInt &RHS) { + APInt::operator=(RHS); + return *this; +} diff --git a/test/SemaCXX/user-defined-conversions.cpp b/test/SemaCXX/user-defined-conversions.cpp new file mode 100644 index 0000000..0a4bb77 --- /dev/null +++ b/test/SemaCXX/user-defined-conversions.cpp @@ -0,0 +1,69 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + operator bool(); +}; + +int& f(bool); +float& f(int); + +void f_test(X x) { + int& i1 = f(x); +} + +struct Y { + operator short(); + operator float(); +}; + +void g(int); + +void g_test(Y y) { + g(y); + short s; + s = y; +} + +struct A { }; +struct B : A { }; + +struct C { + operator B&(); +}; + +// Test reference binding via an lvalue conversion function. +void h(volatile A&); +void h_test(C c) { + h(c); +} + +// Test conversion followed by copy-construction +struct FunkyDerived; + +struct Base { + Base(const FunkyDerived&); +}; + +struct Derived : Base { }; + +struct FunkyDerived : Base { }; + +struct ConvertibleToBase { + operator Base(); +}; + +struct ConvertibleToDerived { + operator Derived(); +}; + +struct ConvertibleToFunkyDerived { + operator FunkyDerived(); +}; + +void test_conversion(ConvertibleToBase ctb, ConvertibleToDerived ctd, + ConvertibleToFunkyDerived ctfd) { + Base b1 = ctb; + Base b2(ctb); + Base b3 = ctd; + Base b4(ctd); + Base b5 = ctfd; +} diff --git a/test/SemaCXX/using-directive.cpp b/test/SemaCXX/using-directive.cpp new file mode 100644 index 0000000..924cf07 --- /dev/null +++ b/test/SemaCXX/using-directive.cpp @@ -0,0 +1,108 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace A { + short i; // expected-note 2{{candidate found by name lookup is 'A::i'}} + namespace B { + long i; // expected-note{{candidate found by name lookup is 'A::B::i'}} + void f() {} // expected-note{{candidate function}} + int k; + namespace E {} // \ + expected-note{{candidate found by name lookup is 'A::B::E'}} + } + + namespace E {} // expected-note{{candidate found by name lookup is 'A::E'}} + + namespace C { + using namespace B; + namespace E {} // \ + expected-note{{candidate found by name lookup is 'A::C::E'}} + } + + void f() {} // expected-note{{candidate function}} + + class K1 { + void foo(); + }; + + void local_i() { + char i; + using namespace A; + using namespace B; + int a[sizeof(i) == sizeof(char)? 1 : -1]; // okay + } + namespace B { + int j; + } + + void ambig_i() { + using namespace A; + using namespace A::B; + (void) i; // expected-error{{reference to 'i' is ambiguous}} + f(); // expected-error{{call to 'f' is ambiguous}} + (void) j; // okay + using namespace C; + (void) k; // okay + using namespace E; // expected-error{{reference to 'E' is ambiguous}} + } + + struct K2 {}; // expected-note{{candidate found by name lookup is 'A::K2'}} +} + +struct K2 {}; // expected-note{{candidate found by name lookup is 'K2'}} + +using namespace A; + +void K1::foo() {} // okay + +// FIXME: Do we want err_ovl_no_viable_function_in_init here? +struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \ + expected-error{{incomplete type}} + +// FIXME: This case is incorrectly diagnosed! +//K2 k3; + + +class X { // expected-note{{candidate found by name lookup is 'X'}} + // FIXME: produce a suitable error message for this + using namespace A; // expected-error{{expected member name or}} +}; + +namespace N { + struct K2; + struct K2 { }; +} + +namespace Ni { + int i(); // expected-note{{candidate found by name lookup is 'Ni::i'}} +} + +namespace NiTest { + using namespace A; + using namespace Ni; + + int test() { + return i; // expected-error{{reference to 'i' is ambiguous}} + } +} + +namespace OneTag { + struct X; // expected-note{{candidate found by name lookup is 'OneTag::X'}} +} + +namespace OneFunction { + void X(); // expected-note{{candidate found by name lookup is 'OneFunction::X'}} +} + +namespace TwoTag { + struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} +} + +namespace FuncHidesTagAmbiguity { + using namespace OneTag; + using namespace OneFunction; + using namespace TwoTag; + + void test() { + (void)X(); // expected-error{{reference to 'X' is ambiguous}} + } +} diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp new file mode 100644 index 0000000..1c5fe74 --- /dev/null +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify -fblocks %s + +extern char version[]; + +class C { +public: + C(int); + void g(int a, ...); + static void h(int a, ...); +}; + +void g(int a, ...); + +void t1() +{ + C c(10); + + g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + g(10, version); +} + +void t2() +{ + C c(10); + + c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + c.g(10, version); + + C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + C::h(10, version); +} + +int (^block)(int, ...); + +void t3() +{ + C c(10); + + block(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic block; call will abort at runtime}} + block(10, version); +} + +class D { +public: + void operator() (int a, ...); +}; + +void t4() +{ + C c(10); + + D d; + + d(10, c); // expected-warning{{Line 48: cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + d(10, version); +} diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp new file mode 100644 index 0000000..4a3b10f --- /dev/null +++ b/test/SemaCXX/virtual-override.cpp @@ -0,0 +1,106 @@ +// RUN: clang-cc -fsyntax-only -faccess-control -verify %s + +namespace T1 { + +class A { + virtual int f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual void f(); // expected-error{{virtual function 'f' has a different return type ('void') than the function it overrides (which has return type 'int')}} +}; + +} + +namespace T2 { + +struct a { }; +struct b { }; + +class A { + virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('struct T2::b *' is not derived from 'struct T2::a *')}} +}; + +} + +namespace T3 { + +struct a { }; +struct b : private a { }; // expected-note{{'private' inheritance specifier here}} + +class A { + virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (conversion from 'struct T3::b' to inaccessible base class 'struct T3::a')}} +}; + +} + +namespace T4 { + +struct a { }; +struct a1 : a { }; +struct b : a, a1 { }; + +class A { + virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (ambiguous conversion from derived class 'struct T4::b' to base class 'struct T4::a':\n\ + struct T4::b -> struct T4::a\n\ + struct T4::b -> struct T4::a1 -> struct T4::a)}} +}; + +} + +namespace T5 { + +struct a { }; + +class A { + virtual a* const f(); + virtual a* const g(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual a* const f(); + virtual a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides ('struct T5::a *' has different qualifiers than 'struct T5::a *const')}} +}; + +} + +namespace T6 { + +struct a { }; + +class A { + virtual const a* f(); + virtual a* g(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual a* f(); + virtual const a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides (class type 'struct T6::a const *' is more qualified than class type 'struct T6::a *'}} +}; + +} + +namespace T7 { + struct a { }; + struct b { }; + + class A { + a* f(); + }; + + class B : A { + virtual b* f(); + }; +} diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp new file mode 100644 index 0000000..c2ac77b --- /dev/null +++ b/test/SemaCXX/virtuals.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class A { + virtual void f(); + virtual void g() = 0; + + void h() = 0; // expected-error {{'h' is not virtual and cannot be declared pure}} + void i() = 1; // expected-error {{initializer on function does not look like a pure-specifier}} + void j() = 0u; // expected-error {{initializer on function does not look like a pure-specifier}} + + + void k(); + +public: + A(int); +}; + +virtual void A::k() { } // expected-error{{'virtual' can only be specified inside the class definition}} + +class B : public A { + // Needs to recognize that overridden function is virtual. + //void g() = 0; + + // Needs to recognize that function does not override. + //void g(int) = 0; +}; + +// Needs to recognize invalid uses of abstract classes. +/* +A fn(A) +{ + A a; + static_cast<A>(0); + try { + } catch(A) { + } +} +*/ diff --git a/test/SemaCXX/warn-for-var-in-else.cpp b/test/SemaCXX/warn-for-var-in-else.cpp new file mode 100644 index 0000000..3368da2 --- /dev/null +++ b/test/SemaCXX/warn-for-var-in-else.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// rdar://6425550 +int bar(); +void do_something(int); + +int foo() { + if (int X = bar()) { + return X; + } else { + do_something(X); // expected-warning{{'X' is always zero in this context}} + } +} + +bool foo2() { + if (bool B = bar()) { + if (int Y = bar()) { + return B; + } else { + do_something(Y); // expected-warning{{'Y' is always zero in this context}} + return B; + } + } else { + if (bool B2 = B) { // expected-warning{{'B' is always false in this context}} + do_something(B); // expected-warning{{'B' is always false in this context}} + } else if (B2) { // expected-warning{{'B2' is always false in this context}} + do_something(B); // expected-warning{{'B' is always false in this context}} + } + return B; // expected-warning{{'B' is always false in this context}} + } +} diff --git a/test/SemaCXX/wchar_t.cpp b/test/SemaCXX/wchar_t.cpp new file mode 100644 index 0000000..fc258da --- /dev/null +++ b/test/SemaCXX/wchar_t.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +wchar_t x; + +void f(wchar_t p) { + wchar_t x; + unsigned wchar_t y; // expected-warning {{'wchar_t' cannot be signed or unsigned}} + signed wchar_t z; // expected-warning {{'wchar_t' cannot be signed or unsigned}} + ++x; +} |