diff options
author | dim <dim@FreeBSD.org> | 2011-06-12 15:46:16 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-06-12 15:46:16 +0000 |
commit | c49018d9cce52d8c9f34b44865ec3ba8e89a1488 (patch) | |
tree | c5e9e10bc189de0058aa763c47b9920a8351b7df /test/SemaCXX | |
parent | 110eaaceddcec790f7e6a5e3bf1261c9aa1e73ab (diff) | |
download | FreeBSD-src-c49018d9cce52d8c9f34b44865ec3ba8e89a1488.zip FreeBSD-src-c49018d9cce52d8c9f34b44865ec3ba8e89a1488.tar.gz |
Vendor import of clang trunk r132879:
http://llvm.org/svn/llvm-project/cfe/trunk@132879
Diffstat (limited to 'test/SemaCXX')
52 files changed, 1996 insertions, 134 deletions
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 2d620b6..9b03feb 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -6,6 +6,8 @@ void f(const type_info &a); // Microsoft doesn't validate exception specification. +namespace microsoft_exception_spec { + void foo(); // expected-note {{previous declaration}} void foo() throw(); // expected-warning {{exception specification in declaration does not match previous declaration}} @@ -22,6 +24,15 @@ struct Derived : Base { virtual void f3(); }; +class A { + virtual ~A() throw(); // expected-note {{overridden virtual function is here}} +}; + +class B : public A { + virtual ~B(); // expected-warning {{exception specification of overriding function is more lax than base version}} +}; + +} // MSVC allows type definition in anonymous union and struct struct A @@ -179,4 +190,65 @@ void static_func(); // expected-note {{previous declaration is here}} static void static_func() // expected-warning {{static declaration of 'static_func' follows non-static declaration}} { -}
\ No newline at end of file +} + +long function_prototype(int a); +long (*function_ptr)(int a); + +void function_to_voidptr_conv() { + void *a1 = function_prototype; + void *a2 = &function_prototype; + void *a3 = function_ptr; +} + + +void pointer_to_integral_type_conv(char* ptr) { + char ch = (char)ptr; + short sh = (short)ptr; + ch = (char)ptr; + sh = (short)ptr; +} + +namespace ms_using_declaration_bug { + +class A { +public: + int f(); +}; + +class B : public A { +private: + using A::f; +}; + +class C : public B { +private: + using B::f; // expected-warning {{using declaration refers to inaccessible member 'ms_using_declaration_bug::B::f', which refers to accessible member 'ms_using_declaration_bug::A::f', accepted for Microsoft compatibility}} +}; + +} + + + +namespace friend_as_a_forward_decl { + +class A { + class Nested { + friend class B; + B* b; + }; + B* b; +}; +B* global_b; + + +void f() +{ + class Local { + friend class Z; + Z* b; + }; + Z* b; +} + + }
\ No newline at end of file diff --git a/test/SemaCXX/PR9572.cpp b/test/SemaCXX/PR9572.cpp index d1b7077..25c0c01 100644 --- a/test/SemaCXX/PR9572.cpp +++ b/test/SemaCXX/PR9572.cpp @@ -1,13 +1,13 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s class Base { - virtual ~Base(); + virtual ~Base(); // expected-note {{implicitly declared private here}} }; -struct Foo : public Base { - const int kBlah = 3; // expected-error{{fields can only be initialized in constructors}} +struct Foo : public Base { // expected-error {{base class 'Base' has private destructor}} + const int kBlah = 3; // expected-warning {{accepted as a C++0x extension}} Foo(); }; struct Bar : public Foo { - Bar() { } + Bar() { } // expected-note {{implicit default destructor for 'Foo' first required here}} }; struct Baz { Foo f; diff --git a/test/SemaCXX/PR9884.cpp b/test/SemaCXX/PR9884.cpp new file mode 100644 index 0000000..ab883c4 --- /dev/null +++ b/test/SemaCXX/PR9884.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class Base { +protected: + Base(int val); +}; + + +class Derived : public Base { +public: + Derived(int val); +}; + + +Derived::Derived(int val) + : Base( val ) +{ +} diff --git a/test/SemaCXX/PR9902.cpp b/test/SemaCXX/PR9902.cpp new file mode 100644 index 0000000..ec76789 --- /dev/null +++ b/test/SemaCXX/PR9902.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +template <class _Tp, class _Up, bool = false> +struct __allocator_traits_rebind +{ +}; + +template <template <class, class...> class _Alloc, class _Tp, class ..._Args, +class _Up> +struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, false> +{ + typedef _Alloc<_Up, _Args...> type; +}; + +template <class Alloc> +struct allocator_traits +{ + template <class T> using rebind_alloc = typename __allocator_traits_rebind<Alloc, T>::type; + template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; +}; + +template <class T> +struct allocator {}; + +int main() +{ + allocator_traits<allocator<char>>::rebind_alloc<int> a; +} diff --git a/test/SemaCXX/PR9908.cpp b/test/SemaCXX/PR9908.cpp new file mode 100644 index 0000000..3b98b72 --- /dev/null +++ b/test/SemaCXX/PR9908.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +template <class _Tp, class _Up> +struct __allocator_traits_rebind +{ + typedef typename _Tp::template rebind<_Up>::other type; +}; + +template <class Alloc> +struct allocator_traits +{ + typedef Alloc allocator_type; + template <class T> using rebind_alloc = typename +__allocator_traits_rebind<allocator_type, T>::type; + template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; +}; + +template <class T> +struct ReboundA {}; + +template <class T> +struct A +{ + typedef T value_type; + + template <class U> struct rebind {typedef ReboundA<U> other;}; +}; + +int main() +{ + allocator_traits<A<char> >::rebind_traits<double> a; +} diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index 4c34447..b9e69b0 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -2,6 +2,8 @@ // Verify that we can't initialize non-aggregates with an initializer // list. +// FIXME: Note that due to a (likely) standard bug, this is technically an +// aggregate. struct NonAggr1 { NonAggr1(int) { } @@ -22,7 +24,7 @@ struct NonAggr4 { virtual void f(); }; -NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}} +NonAggr1 na1 = { 17 }; NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}} NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}} NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}} diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp new file mode 100644 index 0000000..f29a932 --- /dev/null +++ b/test/SemaCXX/alias-template.cpp @@ -0,0 +1,147 @@ +// RUN: %clang_cc1 -verify -std=c++0x %s + +namespace RedeclAliasTypedef { + template<typename U> using T = int; + template<typename U> using T = int; + template<typename U> using T = T<U>; +} + +namespace IllegalTypeIds { + template<typename U> using A = void(int n = 0); // expected-error {{default arguments can only be specified for parameters in a function declaration}} + template<typename U> using B = inline void(int n); // expected-error {{type name does not allow function specifier}} + template<typename U> using C = virtual void(int n); // expected-error {{type name does not allow function specifier}} + template<typename U> using D = explicit void(int n); // expected-error {{type name does not allow function specifier}} + template<typename U> using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}} + // FIXME: this is illegal; we incorrectly accept it for typedefs too. + template<typename U> using F = void(*)(int n) &&; // expected-err + template<typename U> using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}} + + template<typename U> using H = void(int n); // ok + template<typename U> using I = void(int n) &&; // ok +} + +namespace IllegalSyntax { + template<typename Z> using ::T = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + template<typename Z> using operator int = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + template<typename Z> using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}} + template<typename Z> using typename ::V = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + template<typename Z> using typename ::operator bool = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +} + +namespace VariableLengthArrays { + template<typename Z> using T = int[42]; // ok + + int n = 32; + template<typename Z> using T = int[n]; // expected-error {{variable length array declaration not allowed at file scope}} + + const int m = 42; + template<typename Z> using U = int[m]; // expected-note {{previous definition}} + template<typename Z> using U = int[42]; // ok + template<typename Z> using U = int; // expected-error {{type alias template redefinition with different types ('int' vs 'int [42]')}} +} + +namespace RedeclFunc { + int f(int, char**); + template<typename Z> using T = int; + T<char> f(int, char **); // ok +} + +namespace LookupFilter { + namespace N { template<typename U> using S = int; } + using namespace N; + template<typename U> using S = S<U>*; // ok +} + +namespace InFunctions { + template<typename...T> struct S0 { + template<typename Z> using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} + U<char> u; + }; + + template<typename Z> using T1 = int; + template<typename Z> using T2 = int[-1]; // expected-error {{array size is negative}} + template<typename...T> struct S3 { // expected-note {{template parameter is declared here}} + template<typename Z> using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + }; + template<typename Z> using Z = Z; +} + +namespace ClassNameRedecl { + class C0 { + // FIXME: this diagnostic is pretty poor + template<typename U> using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}} + }; + class C1 { + // FIXME: this diagnostic is pretty poor + template<typename U> using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}} + }; + class C2 { + template<typename U> using C0 = C1; // ok + }; + template<typename...T> class C3 { + template<typename U> using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} + }; + template<typename T> class C4 { // expected-note {{template parameter is declared here}} + template<typename U> using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + }; + class C5 { + class c; // expected-note {{previous definition}} + template<typename U> using c = int; // expected-error {{redefinition of 'c' as different kind of symbol}} + class d; // expected-note {{previous definition}} + template<typename U> using d = d; // expected-error {{redefinition of 'd' as different kind of symbol}} + }; + class C6 { + class c { template<typename U> using C6 = int; }; // ok + }; +} + +class CtorDtorName { + template<typename T> using X = CtorDtorName; + X<int>(); // expected-error {{expected member name}} + ~X<int>(); // expected-error {{destructor cannot be declared using a type alias}} +}; + +namespace TagName { + template<typename Z> using S = struct { int n; }; // expected-error {{can not be defined}} + template<typename Z> using T = class { int n; }; // expected-error {{can not be defined}} + template<typename Z> using U = enum { a, b, c }; // expected-error {{can not be defined}} + template<typename Z> using V = struct V { int n; }; // expected-error {{redefinition of 'V' as different kind of symbol}} \ + expected-error {{'TagName::V' can not be defined in a type alias template}} \ + expected-note {{previous definition is here}} +} + +namespace StdExample { + template<typename T, typename U> struct pair; + + template<typename T> using handler_t = void (*)(T); + extern handler_t<int> ignore; + extern void (*ignore)(int); + // FIXME: we recover as if cell is an undeclared variable. the diagnostics are terrible! + template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} \ + expected-error {{'T' does not refer to a value}} \ + expected-note {{declared here}} \ + expected-error {{expected ';' after alias declaration}} +} + +namespace Access { + class C0 { + template<typename Z> using U = int; // expected-note {{declared private here}} + }; + C0::U<int> v; // expected-error {{'U' is a private member}} + class C1 { + public: + template<typename Z> using U = int; + }; + C1::U<int> w; // ok +} + +namespace VoidArg { + template<typename Z> using V = void; + V<int> f(int); // ok + V<char> g(V<double>); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}} +} + +namespace Curried { + template<typename T, typename U> struct S; + template<typename T> template<typename U> using SS = S<T, U>; // expected-error {{extraneous template parameter list in alias template declaration}} +} diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 553ae65..2dd7ab8 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s struct X { union { float f3; @@ -17,7 +17,7 @@ struct X { void test_unqual_references(); - struct { + struct { // expected-warning{{anonymous structs are a GNU extension}} int a; float b; }; @@ -125,7 +125,7 @@ typedef struct _s { // <rdar://problem/7987650> namespace test4 { class A { - struct { + struct { // expected-warning{{anonymous structs are a GNU extension}} int s0; // expected-note {{declared private here}} double s1; // expected-note {{declared private here}} union { @@ -136,7 +136,7 @@ namespace test4 { union { int u0; // expected-note {{declared private here}} double u1; // expected-note {{declared private here}} - struct { + struct { // expected-warning{{anonymous structs are a GNU extension}} int us0; // expected-note {{declared private here}} double us1; // expected-note {{declared private here}} }; @@ -175,3 +175,25 @@ void foo_PR6741() { }; } } + +namespace PR8326 { + template <class T> + class Foo { + public: + Foo() + : x(0) + , y(1){ + } + + private: + const union { // expected-warning{{anonymous union cannot be 'const'}} + struct { // expected-warning{{anonymous structs are a GNU extension}} + T x; + T y; + }; + T v[2]; + }; + }; + + Foo<int> baz; +} diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index 40fe0e0..725f018 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -9,8 +9,13 @@ struct align_member { int member [[align(8)]]; }; +typedef char align_typedef [[align(8)]]; +template<typename T> using align_alias_template = align_typedef; + static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong"); static_assert(alignof(align_small) == 1, "j's alignment is wrong"); static_assert(alignof(align_multiple) == 8, "l's alignment is wrong"); static_assert(alignof(align_member) == 8, "quuux's alignment is wrong"); static_assert(sizeof(align_member) == 8, "quuux's size is wrong"); +static_assert(alignof(align_typedef) == 8, "typedef's alignment is wrong"); +static_assert(alignof(align_alias_template<int>) == 8, "alias template's alignment is wrong"); diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp index b7d3999..eaf0d0c 100644 --- a/test/SemaCXX/attr-noreturn.cpp +++ b/test/SemaCXX/attr-noreturn.cpp @@ -1,5 +1,22 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// Reachability tests have to come first because they get suppressed +// if any errors have occurred. +namespace test5 { + struct A { + __attribute__((noreturn)) void fail(); + void nofail(); + } a; + + int &test1() { + a.nofail(); + } // expected-warning {{control reaches end of non-void function}} + + int &test2() { + a.fail(); + } +} + // PR5620 void f0() __attribute__((__noreturn__)); void f1(void (*)()); diff --git a/test/SemaCXX/attr-regparm.cpp b/test/SemaCXX/attr-regparm.cpp index b98631a..91ee613 100644 --- a/test/SemaCXX/attr-regparm.cpp +++ b/test/SemaCXX/attr-regparm.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-pc-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin10 %s // PR7025 struct X0 { diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp index 52140cb..44fa0ce 100644 --- a/test/SemaCXX/class.cpp +++ b/test/SemaCXX/class.cpp @@ -34,7 +34,7 @@ public: enum E1 { en1, en2 }; - int i = 0; // expected-error {{fields can only be initialized in constructors}} + int i = 0; // expected-warning {{in-class initialization of non-static data member accepted as a C++0x extension}} static int si = 0; // expected-error {{non-const static data member must be initialized out of line}} static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}} static const int nci = vs; // expected-error {{in-class initializer is not a constant expression}} diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index fdda7ac..b069abc 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -verify %s +#include <stddef.h> + typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; @@ -50,3 +52,12 @@ namespace test2 { A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} }; } + +void test3() { + int a = NULL; // expected-warning {{implicit conversion of NULL constant to integer}} + int b; + b = NULL; // expected-warning {{implicit conversion of NULL constant to integer}} + int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to integer}} + int d; + d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to integer}} +} diff --git a/test/SemaCXX/copy-constructor-error.cpp b/test/SemaCXX/copy-constructor-error.cpp index 9809bfc..64a7d58 100644 --- a/test/SemaCXX/copy-constructor-error.cpp +++ b/test/SemaCXX/copy-constructor-error.cpp @@ -13,10 +13,10 @@ void g() { namespace PR6064 { struct A { A() { } - inline A(A&, int); + inline A(A&, int); // expected-note {{was not a special member function}} }; - A::A(A&, int = 0) { } + A::A(A&, int = 0) { } // expected-warning {{makes this constructor a copy constructor}} void f() { A const a; diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp new file mode 100644 index 0000000..61aee0e --- /dev/null +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct non_copiable { + non_copiable(const non_copiable&) = delete; // expected-note {{marked deleted here}} + non_copiable& operator = (const non_copiable&) = delete; // expected-note {{explicitly deleted}} + non_copiable() = default; +}; + +struct non_const_copy { + non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} + non_const_copy& operator = (non_const_copy&) & = default; // expected-note {{not viable}} + non_const_copy& operator = (non_const_copy&) && = default; // expected-note {{not viable}} + non_const_copy() = default; // expected-note {{not viable}} +}; + +void fn1 () { + non_copiable nc; + non_copiable nc2 = nc; // expected-error {{deleted constructor}} + nc = nc; // expected-error {{deleted operator}} + + non_const_copy ncc; + non_const_copy ncc2 = ncc; + ncc = ncc2; + const non_const_copy cncc; + non_const_copy ncc3 = cncc; // expected-error {{no matching}} + ncc = cncc; // expected-error {{no viable overloaded}} +}; + +struct non_const_derived : non_const_copy { + non_const_derived(const non_const_derived&) = default; // expected-error {{requires it to be non-const}} + non_const_derived& operator =(non_const_derived&) = default; +}; + +struct bad_decls { + bad_decls(volatile bad_decls&) = default; // expected-error {{may not be volatile}} + bad_decls&& operator = (bad_decls) = default; // expected-error 2{{lvalue reference}} + bad_decls& operator = (volatile bad_decls&) = default; // expected-error {{may not be volatile}} + bad_decls& operator = (const bad_decls&) const = default; // expected-error {{may not have 'const' or 'volatile' qualifiers}} +}; + +struct A {}; struct B {}; + +struct except_spec_a { + virtual ~except_spec_a() throw(A); + except_spec_a() throw(A); +}; +struct except_spec_b { + virtual ~except_spec_b() throw(B); + except_spec_b() throw(B); +}; + +struct except_spec_d_good : except_spec_a, except_spec_b { + ~except_spec_d_good(); +}; +except_spec_d_good::~except_spec_d_good() = default; +// FIXME: This should error in the virtual override check. +// It doesn't because we generate the implicit specification later than +// appropriate. +struct except_spec_d_bad : except_spec_a, except_spec_b { + ~except_spec_d_bad() = default; +}; + +// FIXME: This should error because the exceptions spec doesn't match. +struct except_spec_d_mismatch : except_spec_a, except_spec_b { + except_spec_d_mismatch() throw(A) = default; +}; +struct except_spec_d_match : except_spec_a, except_spec_b { + except_spec_d_match() throw(A, B) = default; +}; diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp new file mode 100644 index 0000000..86c5fd1 --- /dev/null +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +void fn() = default; // expected-error {{only special member}} +struct foo { + void fn() = default; // expected-error {{only special member}} + + foo() = default; + foo(const foo&) = default; + foo(foo&) = default; + foo& operator = (const foo&) = default; + foo& operator = (foo&) = default; + ~foo() = default; +}; + +struct bar { + bar(); + bar(const bar&); + bar(bar&); + bar& operator = (const bar&); + bar& operator = (bar&); + ~bar(); +}; + +bar::bar() = default; +bar::bar(const bar&) = default; +bar::bar(bar&) = default; +bar& bar::operator = (const bar&) = default; +bar& bar::operator = (bar&) = default; +bar::~bar() = default; + +// FIXME: static_assert(__is_trivial(foo), "foo should be trivial"); + +static_assert(!__has_trivial_destructor(bar), "bar's destructor isn't trivial"); +static_assert(!__has_trivial_constructor(bar), + "bar's default constructor isn't trivial"); +static_assert(!__has_trivial_copy(bar), "bar has no trivial copy"); +static_assert(!__has_trivial_assign(bar), "bar has no trivial assign"); + +void tester() { + foo f, g(f); + bar b, c(b); + f = g; + b = c; +} + diff --git a/test/SemaCXX/cxx0x-delegating-ctors.cpp b/test/SemaCXX/cxx0x-delegating-ctors.cpp index b211cb1..a3e6ff3 100644 --- a/test/SemaCXX/cxx0x-delegating-ctors.cpp +++ b/test/SemaCXX/cxx0x-delegating-ctors.cpp @@ -7,8 +7,9 @@ struct foo { foo(int, int); foo(bool); foo(char); - foo(float*); - foo(float&); + foo(const float*); + foo(const float&); + foo(void*); }; // Good @@ -21,16 +22,27 @@ foo::foo () : foo(-1) { foo::foo (int, int) : foo() { } -foo::foo (bool) : foo(true) { // expected-error{{delegates to itself}} +foo::foo (bool) : foo(true) { // expected-error{{creates a delegation cycle}} } // Good -foo::foo (float* f) : foo(*f) { +foo::foo (const float* f) : foo(*f) { // expected-note{{it delegates to}} } -// FIXME: This should error -foo::foo (float &f) : foo(&f) { +foo::foo (const float &f) : foo(&f) { //expected-error{{creates a delegation cycle}} \ + //expected-note{{which delegates to}} } foo::foo (char) : i(3), foo(3) { // expected-error{{must appear alone}} } + +// This should not cause an infinite loop +foo::foo (void*) : foo(4.0f) { +} + +struct deleted_dtor { + ~deleted_dtor() = delete; // expected-note{{function has been explicitly marked deleted here}} + deleted_dtor(); + deleted_dtor(int) : deleted_dtor() // expected-error{{attempt to use a deleted function}} + {} +}; diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp new file mode 100644 index 0000000..dcb6ba2 --- /dev/null +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct non_trivial { + non_trivial(); + non_trivial(const non_trivial&); + non_trivial& operator = (const non_trivial&); + ~non_trivial(); +}; + +union bad_union { // expected-note {{marked deleted here}} + non_trivial nt; +}; +bad_union u; // expected-error {{call to deleted constructor}} +union bad_union2 { // expected-note {{marked deleted here}} + const int i; +}; +bad_union2 u2; // expected-error {{call to deleted constructor}} + +struct bad_anon { // expected-note {{marked deleted here}} + union { + non_trivial nt; + }; +}; +bad_anon a; // expected-error {{call to deleted constructor}} +struct bad_anon2 { // expected-note {{marked deleted here}} + union { + const int i; + }; +}; +bad_anon2 a2; // expected-error {{call to deleted constructor}} + +// This would be great except that we implement +union good_union { + const int i; + float f; +}; +good_union gu; +struct good_anon { + union { + const int i; + float f; + }; +}; +good_anon ga; + +struct good : non_trivial { + non_trivial nt; +}; +good g; + +struct bad_const { // expected-note {{marked deleted here}} + const good g; +}; +bad_const bc; // expected-error {{call to deleted constructor}} + +struct good_const { + const non_trivial nt; +}; +good_const gc; + +struct no_default { + no_default() = delete; +}; +struct no_dtor { + ~no_dtor() = delete; +}; + +struct bad_field_default { // expected-note {{marked deleted here}} + no_default nd; +}; +bad_field_default bfd; // expected-error {{call to deleted constructor}} +struct bad_base_default : no_default { // expected-note {{marked deleted here}} +}; +bad_base_default bbd; // expected-error {{call to deleted constructor}} + +struct bad_field_dtor { // expected-note {{marked deleted here}} + no_dtor nd; +}; +bad_field_dtor bfx; // expected-error {{call to deleted constructor}} +struct bad_base_dtor : no_dtor { // expected-note {{marked deleted here}} +}; +bad_base_dtor bbx; // expected-error {{call to deleted constructor}} + +struct ambiguous_default { + ambiguous_default(); + ambiguous_default(int = 2); +}; +struct has_amb_field { // expected-note {{marked deleted here}} + ambiguous_default ad; +}; +has_amb_field haf; // expected-error {{call to deleted constructor}} + +class inaccessible_default { + inaccessible_default(); +}; +struct has_inacc_field { // expected-note {{marked deleted here}} + inaccessible_default id; +}; +has_inacc_field hif; // expected-error {{call to deleted constructor}} + +class friend_default { + friend struct has_friend; + friend_default(); +}; +struct has_friend { + friend_default fd; +}; +has_friend hf; + +struct defaulted_delete { + no_default nd; + defaulted_delete() = default; // expected-note {{marked deleted here}} +}; +defaulted_delete dd; // expected-error {{call to deleted constructor}} + +struct late_delete { + no_default nd; + late_delete(); +}; +late_delete::late_delete() = default; // expected-error {{would delete it}} diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp new file mode 100644 index 0000000..666e64b --- /dev/null +++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct non_trivial { + non_trivial(); + non_trivial(const non_trivial&); + non_trivial& operator = (const non_trivial&); + ~non_trivial(); +}; + +union u { + non_trivial nt; +}; + +union bad { + static int i; // expected-error {{static data member}} +}; + +struct s { + union { + non_trivial nt; + }; +}; diff --git a/test/SemaCXX/default-arg-special-member.cpp b/test/SemaCXX/default-arg-special-member.cpp new file mode 100644 index 0000000..8402d382 --- /dev/null +++ b/test/SemaCXX/default-arg-special-member.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wno-default-arg-special-member -Werror -fsyntax-only %s + +class foo { + foo(foo&, int); // expected-note {{was not a special member function}} + foo(int); // expected-note {{was not a special member function}} + foo(const foo&); // expected-note {{was a copy constructor}} +}; + +foo::foo(foo&, int = 0) { } // expected-warning {{makes this constructor a copy constructor}} +foo::foo(int = 0) { } // expected-warning {{makes this constructor a default constructor}} +foo::foo(const foo& = 0) { } //expected-warning {{makes this constructor a default constructor}} diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp index 9da8556..e783f49 100644 --- a/test/SemaCXX/default-constructor-initializers.cpp +++ b/test/SemaCXX/default-constructor-initializers.cpp @@ -59,3 +59,10 @@ namespace PR7948 { struct S { const int x; ~S(); }; const S arr[2] = { { 42 } }; } + +// This is valid +union U { + const int i; + float f; +}; +U u; diff --git a/test/SemaCXX/defaulted-ctor-loop.cpp b/test/SemaCXX/defaulted-ctor-loop.cpp new file mode 100644 index 0000000..6a41972 --- /dev/null +++ b/test/SemaCXX/defaulted-ctor-loop.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +// WARNING: This test may recurse infinitely if failing. + +struct foo; +struct bar { + bar(foo&); +}; +struct foo { + bar b; + foo() + : b(b) // expected-warning{{field is uninitialized}} + {} +}; diff --git a/test/SemaCXX/deleted-function-extension.cpp b/test/SemaCXX/deleted-function-extension.cpp deleted file mode 100644 index fdf5ac8..0000000 --- a/test/SemaCXX/deleted-function-extension.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s - -struct A { - A(const A&) = delete; // expected-warning {{deleted function definition accepted as a C++0x extension}} - A& operator=(const A&) = delete; // expected-warning {{deleted function definition accepted as a C++0x extension}} -}; - -void f() = delete; // expected-warning {{deleted function definition accepted as a C++0x extension}} diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index b3e1296..6a8965c 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -7,9 +7,8 @@ void fn() = delete; // expected-note {{candidate function has been explicitly de 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 fn3() = delete; // expected-note {{previous definition is here}} +void fn3() { // expected-error {{redefinition}} } void ov(int) {} // expected-note {{candidate function}} diff --git a/test/SemaCXX/dependent-noexcept-unevaluated.cpp b/test/SemaCXX/dependent-noexcept-unevaluated.cpp new file mode 100644 index 0000000..5bf6f9e --- /dev/null +++ b/test/SemaCXX/dependent-noexcept-unevaluated.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x %s + +template <class T> +T&& +declval() noexcept; + +template <class T> +struct some_trait +{ + static const bool value = false; +}; + +template <class T> +void swap(T& x, T& y) noexcept(some_trait<T>::value) +{ + T tmp(static_cast<T&&>(x)); + x = static_cast<T&&>(y); + y = static_cast<T&&>(tmp); +} + +template <class T, unsigned N> +struct array +{ + T data[N]; + + void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>()))); +}; + +struct DefaultOnly +{ + DefaultOnly() = default; + DefaultOnly(const DefaultOnly&) = delete; + DefaultOnly& operator=(const DefaultOnly&) = delete; + ~DefaultOnly() = default; +}; + +int main() +{ + array<DefaultOnly, 1> a, b; +} + diff --git a/test/SemaCXX/dependent-types.cpp b/test/SemaCXX/dependent-types.cpp index d9b5323..053e79b 100644 --- a/test/SemaCXX/dependent-types.cpp +++ b/test/SemaCXX/dependent-types.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify -std=c++0x %s + +template<typename T> using U = int &; template<typename T, int Size> void f() { T x1; @@ -7,4 +9,5 @@ template<typename T, int Size> void f() { T x4[]; // expected-error{{needs an explicit size or an initializer}} T x5[Size]; int x6[Size]; + U<T> x7; // expected-error{{declaration of reference variable 'x7' requires an initializer}} } diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index 01f21de..ec0539b 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wnon-virtual-dtor -verify %s +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s class A { public: ~A(); @@ -173,6 +173,179 @@ template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' h TS2<int> foo; // expected-note {{instantiation}} } +namespace dnvd { // delete-non-virtual-dtor warning +struct NP {}; + +struct B { // expected-warning {{has virtual functions but non-virtual destructor}} + virtual void foo(); +}; + +struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} + +struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}} + +struct VB { + virtual void foo(); + virtual ~VB(); +}; + +struct VD: VB {}; + +struct VF final: VB {}; + +template <typename T> +class simple_ptr { +public: + simple_ptr(T* t): _ptr(t) {} + ~simple_ptr() { delete _ptr; } // \ + // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \ + // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}} + T& operator*() const { return *_ptr; } +private: + T* _ptr; +}; + +template <typename T> +class simple_ptr2 { +public: + simple_ptr2(T* t): _ptr(t) {} + ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} + T& operator*() const { return *_ptr; } +private: + T* _ptr; +}; + +void use(B&); +void use(VB&); + +void nowarnstack() { + B b; use(b); + D d; use(d); + F f; use(f); + VB vb; use(vb); + VD vd; use(vd); + VF vf; use(vf); +} + +void nowarnnonpoly() { + { + NP* np = new NP(); + delete np; + } + { + NP* np = new NP[4]; + delete[] np; + } +} + +void nowarnarray() { + { + B* b = new B[4]; + delete[] b; + } + { + D* d = new D[4]; + delete[] d; + } + { + VB* vb = new VB[4]; + delete[] vb; + } + { + VD* vd = new VD[4]; + delete[] vd; + } +} + +template <typename T> +void nowarntemplate() { + { + T* t = new T(); + delete t; + } + { + T* t = new T[4]; + delete[] t; + } +} + +void nowarn0() { + { + F* f = new F(); + delete f; + } + { + VB* vb = new VB(); + delete vb; + } + { + VB* vb = new VD(); + delete vb; + } + { + VD* vd = new VD(); + delete vd; + } + { + VF* vf = new VF(); + delete vf; + } +} + +void warn0() { + { + B* b = new B(); + delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} + } + { + B* b = new D(); + delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} + } + { + D* d = new D(); + delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}} + } +} + +void nowarn1() { + { + simple_ptr<F> f(new F()); + use(*f); + } + { + simple_ptr<VB> vb(new VB()); + use(*vb); + } + { + simple_ptr<VB> vb(new VD()); + use(*vb); + } + { + simple_ptr<VD> vd(new VD()); + use(*vd); + } + { + simple_ptr<VF> vf(new VF()); + use(*vf); + } +} + +void warn1() { + { + simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}} + use(*b); + } + { + simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}} + use(*b); + } + { + simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}} + use(*d); + } +} +} + namespace PR9238 { class B { public: ~B(); }; class C : virtual B { public: ~C() { } }; diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index 8c4bfe7..fc871cf 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -109,3 +109,13 @@ void PR9333() { scoped_enum e = scoped_enum::yes; if (e == scoped_enum::no) { } } + +// <rdar://problem/9366066> +namespace rdar9366066 { + enum class X : unsigned { value }; + + void f(X x) { + x % X::value; // expected-error{{invalid operands to binary expression ('rdar9366066::X' and 'rdar9366066::X')}} + x % 8; // expected-error{{invalid operands to binary expression ('rdar9366066::X' and 'int')}} + } +} diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp index c4e9dcc..95ece48 100644 --- a/test/SemaCXX/expressions.cpp +++ b/test/SemaCXX/expressions.cpp @@ -32,3 +32,34 @@ namespace test1 { bar(x += E_zero); // expected-error {{incompatible type}} } } + +int test2(int x) { + return x && 4; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + + return x && sizeof(int) == 4; // no warning, RHS is logical op. + return x && true; + return x && false; + return x || true; + return x || false; + + return x && (unsigned)0; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + + return x || (unsigned)1; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + + return x || 0; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x || 1; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x || -1; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x || 5; // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x && 0; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x && 1; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x && -1; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x && 5; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x || (0); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x || (1); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x || (-1); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x || (5); // expected-warning {{use of logical || with constant operand; switch to bitwise | or remove constant}} + return x && (0); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x && (1); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x && (-1); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + return x && (5); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} +} diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp new file mode 100644 index 0000000..ec37a0c --- /dev/null +++ b/test/SemaCXX/generalized-initializers.cpp @@ -0,0 +1,174 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +// XFAIL: * + +template <typename T, typename U> +struct same_type { static const bool value = false; }; +template <typename T> +struct same_type<T, T> { static const bool value = true; }; + +namespace std { + typedef decltype(sizeof(int)) size_t; + + // libc++'s implementation + template <class _E> + class initializer_list + { + const _E* __begin_; + size_t __size_; + + initializer_list(const _E* __b, size_t __s) + : __begin_(__b), + __size_(__s) + {} + + public: + typedef _E value_type; + typedef const _E& reference; + typedef const _E& const_reference; + typedef size_t size_type; + + typedef const _E* iterator; + typedef const _E* const_iterator; + + initializer_list() : __begin_(nullptr), __size_(0) {} + + size_t size() const {return __size_;} + const _E* begin() const {return __begin_;} + const _E* end() const {return __begin_ + __size_;} + }; +} + +namespace integral { + + void initialization() { + { const int a{}; static_assert(a == 0, ""); } + { const int a = {}; static_assert(a == 0, ""); } + { const int a{1}; static_assert(a == 1, ""); } + { const int a = {1}; static_assert(a == 1, ""); } + { const int a{1, 2}; } // expected-error {{excess elements}} + { const int a = {1, 2}; } // expected-error {{excess elements}} + { const short a{100000}; } // expected-error {{narrowing conversion}} + { const short a = {100000}; } // expected-error {{narrowing conversion}} + } + + int function_call() { + void takes_int(int); + takes_int({1}); + + int ar[10]; + (void) ar[{1}]; // expected-error {{initializer list is illegal with the built-in index operator}} + + return {1}; + } + + void inline_init() { + (void) int{1}; + (void) new int{1}; + } + + void initializer_list() { + std::initializer_list<int> il = { 1, 2, 3 }; + std::initializer_list<double> dl = { 1.0, 2.0, 3 }; + auto l = {1, 2, 3, 4}; + static_assert(same_type<decltype(l), std::initializer_list<int>>::value, ""); + auto bl = {1, 2.0}; // expected-error {{cannot deduce}} + + for (int i : {1, 2, 3, 4}) {} + } + + struct A { + int i; + A() : i{1} {} + }; + +} + +namespace objects { + + template <int N> + struct A { + A() { static_assert(N == 0, ""); } + A(int, double) { static_assert(N == 1, ""); } + A(int, int) { static_assert(N == 2, ""); } + A(std::initializer_list<int>) { static_assert(N == 3, ""); } + }; + + void initialization() { + { A<0> a{}; } + { A<0> a = {}; } + { A<1> a{1, 1.0}; } + { A<1> a = {1, 1.0}; } + { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; } + { A<3> a = {1, 2, 3, 4, 5, 6, 7, 8}; } + { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; } + { A<3> a{1, 2}; } + } + + struct C { + C(); + C(int, double); + C(int, int); + C(std::initializer_list<int>); + + int operator[](C); + }; + + C function_call() { + void takes_C(C); + takes_C({1, 1.0}); + + C c; + c[{1, 1.0}]; + + return {1, 1.0}; + } + + void inline_init() { + (void) A<1>{1, 1.0}; + (void) new A<1>{1, 1.0}; + } + + struct B { + B(C, int, C); + }; + + void nested_init() { + B b{{1, 1.0}, 2, {3, 4, 5, 6, 7}}; + } +} + +namespace litb { + + // invalid + struct A { int a[2]; A():a({1, 2}) { } }; // expected-error {{}} + + // invalid + int a({0}); // expected-error {{}} + + // invalid + int const &b({0}); // expected-error {{}} + + struct C { explicit C(int, int); C(int, long); }; + + // invalid + C c({1, 2}); // expected-error {{}} + + // valid (by copy constructor). + C d({1, 2L}); // expected-error {{}} + + // valid + C e{1, 2}; + + struct B { + template<typename ...T> + B(std::initializer_list<int>, T ...); + }; + + // invalid (the first phase only considers init-list ctors) + // (for the second phase, no constructor is viable) + B f{1, 2, 3}; + + // valid (T deduced to <>). + B g({1, 2, 3}); + +} diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp new file mode 100644 index 0000000..81babc0 --- /dev/null +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x -Wall %s + +template<bool b> struct ExceptionIf { static int f(); }; +template<> struct ExceptionIf<false> { typedef int f; }; + +// The exception specification of a defaulted default constructor depends on +// the contents of in-class member initializers. However, the in-class member +// initializers can depend on the exception specification of the constructor, +// since the class is considered complete within them. We reject any such cases. +namespace InClassInitializers { + // Noexcept::Noexcept() is implicitly declared as noexcept(false), because it + // directly invokes ThrowSomething(). However... + // + // If noexcept(Noexcept()) is false, then Noexcept() is a constant expression, + // so noexcept(Noexcept()) is true. But if noexcept(Noexcept()) is true, then + // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept()) + // is false. + bool ThrowSomething() noexcept(false); + struct ConstExpr { + bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{exception specification is not available until end of class definition}} + }; + // We can use it now. + bool w = noexcept(ConstExpr()); + + // Much more obviously broken: we can't parse the initializer without already + // knowing whether it produces a noexcept expression. + struct TemplateArg { + int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{exception specification is not available until end of class definition}} + }; + bool x = noexcept(TemplateArg()); + + // And within a nested class. + struct Nested { + struct Inner { + int n = ExceptionIf<noexcept(Nested())>::f(); // expected-error {{exception specification is not available until end of class definition}} + } inner; + }; + bool y = noexcept(Nested()); + bool z = noexcept(Nested::Inner()); +} + +// FIXME: +// The same problem arises in delayed parsing of exception specifications, +// which clang does not yet support. +namespace ExceptionSpecification { + struct Nested { // expected-note {{not complete}} + struct T { + T() noexcept(!noexcept(Nested())); // expected-error {{incomplete type}} + } t; + }; +} + +// FIXME: +// The same problem arises in delayed parsing of default arguments, +// which clang does not yet support. +namespace DefaultArgument { + // FIXME: this diagnostic is completely wrong. + struct Default { // expected-note {{explicitly marked deleted here}} + struct T { + T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to deleted constructor}} + } t; + }; +} diff --git a/test/SemaCXX/implicit-member-functions.cpp b/test/SemaCXX/implicit-member-functions.cpp index 5333094..8451739 100644 --- a/test/SemaCXX/implicit-member-functions.cpp +++ b/test/SemaCXX/implicit-member-functions.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s struct A { }; -A::A() { } // expected-error {{definition of implicitly declared constructor}} +A::A() { } // expected-error {{definition of implicitly declared default constructor}} struct B { }; B::B(const B&) { } // expected-error {{definition of implicitly declared copy constructor}} diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 68af415..981bae7 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -124,10 +124,10 @@ namespace PR9025 { return fun.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} } - S fun2(); // expected-note{{possibly valid overload here}} - S fun2(int i); // expected-note{{possibly valid overload here}} + S fun2(); + S fun2(int i); int g2() { - return fun2.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it?}} + return fun2.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} } S fun3(int i=0); @@ -140,4 +140,10 @@ namespace PR9025 { int g4() { return fun4.x; // expected-error{{base of member reference is a function; perhaps you meant to call it?}} } + + S fun5(int i); // expected-note{{possibly valid overload here}} + S fun5(float f); // expected-note{{possibly valid overload here}} + int g5() { + return fun5.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it?}} + } } diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp new file mode 100644 index 0000000..1b8c523 --- /dev/null +++ b/test/SemaCXX/member-init.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x -Wall %s + +struct Bitfield { + int n : 3 = 7; // expected-error {{bitfield member cannot have an in-class initializer}} +}; + +int a; +class NoWarning { + int &n = a; +public: + int &GetN() { return n; } +}; + +bool b(); +int k; +struct Recurse { + int &n = b() ? Recurse().n : k; // ok +}; + +struct UnknownBound { + int as[] = { 1, 2, 3 }; // expected-error {{array bound cannot be deduced from an in-class initializer}} + int bs[4] = { 4, 5, 6, 7 }; + int cs[] = { 8, 9, 10 }; // expected-error {{array bound cannot be deduced from an in-class initializer}} +}; + +template<int n> struct T { static const int B; }; +template<> struct T<2> { template<int C, int D> using B = int; }; +const int C = 0, D = 0; +struct S { + int as[] = { decltype(x)::B<C, D>(0) }; // expected-error {{array bound cannot be deduced from an in-class initializer}} + T<sizeof(as) / sizeof(int)> x; // expected-error {{requires a type specifier}} +}; + +struct ThrowCtor { ThrowCtor(int) noexcept(false); }; +struct NoThrowCtor { NoThrowCtor(int) noexcept(true); }; + +struct Throw { ThrowCtor tc = 42; }; +struct NoThrow { NoThrowCtor tc = 42; }; + +static_assert(!noexcept(Throw()), "incorrect exception specification"); +static_assert(noexcept(NoThrow()), "incorrect exception specification"); + +struct CheckExcSpec { + CheckExcSpec() noexcept(true) = default; + int n = 0; +}; +struct CheckExcSpecFail { + CheckExcSpecFail() noexcept(true) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} + ThrowCtor tc = 123; +}; diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index 31c651a..de3b211 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -271,3 +271,28 @@ namespace rdar8358512 { template void B<int>::test0b(); // expected-note {{in instantiation}} } + +namespace PR9973 { + template<class R, class T> struct dm + { + typedef R T::*F; + F f_; + template<class U> int & call(U u) + { return u->*f_; } // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type '<bound member function type>'}} + + template<class U> int operator()(U u) + { call(u); } // expected-note{{in instantiation of}} + }; + + template<class R, class T> + dm<R, T> mem_fn(R T::*) ; + + struct test + { int nullary_v(); }; + + void f() + { + test* t; + mem_fn(&test::nullary_v)(t); // expected-note{{in instantiation of}} + } +} diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index 84c80aa..d69af58 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -60,6 +60,10 @@ nullptr_t f(nullptr_t null) // You can reinterpret_cast nullptr to an integer. (void)reinterpret_cast<uintptr_t>(nullptr); + (void)reinterpret_cast<uintptr_t>(*pn); + + int *ip = *pn; + if (*pn) { } // You can throw nullptr. throw nullptr; @@ -104,3 +108,56 @@ namespace test3 { f("%p", nullptr); } } + +int array0[__is_scalar(nullptr_t)? 1 : -1]; +int array1[__is_pod(nullptr_t)? 1 : -1]; +int array2[sizeof(nullptr_t) == sizeof(void*)? 1 : -1]; + +// FIXME: when we implement constexpr, this will be testable. +#if 0 +int relational0[nullptr < nullptr? -1 : 1]; +int relational1[nullptr > nullptr? -1 : 1]; +int relational2[nullptr <= nullptr? 1 : -1]; +int relational3[nullptr >= nullptr? 1 : -1]; +int equality[nullptr == nullptr? 1 : -1]; +int inequality[nullptr != nullptr? -1 : 1]; +#endif + +namespace overloading { + int &f1(int*); + float &f1(bool); + + void test_f1() { + int &ir = (f1)(nullptr); + } + + struct ConvertsToNullPtr { + operator nullptr_t() const; + }; + + void test_conversion(ConvertsToNullPtr ctn) { + (void)(ctn == ctn); + (void)(ctn != ctn); + (void)(ctn <= ctn); + (void)(ctn >= ctn); + (void)(ctn < ctn); + (void)(ctn > ctn); + } +} + +namespace templates { + template<typename T, nullptr_t Value> + struct X { + X() { ptr = Value; } + + T *ptr; + }; + + X<int, nullptr> x; + + + template<int (*fp)(int), int* p, int A::* pmd, int (A::*pmf)(int)> + struct X2 {}; + + X2<nullptr, nullptr, nullptr, nullptr> x2; +} diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 81a88a3..9cc4899 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -503,3 +503,25 @@ namespace rdar8499524 { g(W()); } } + +namespace rdar9173984 { + template <typename T, unsigned long N> int &f(const T (&)[N]); + template <typename T> float &f(const T *); + + void test() { + int arr[2] = {0, 0}; + int *arrp = arr; + int &ir = f(arr); + float &fr = f(arrp); + } +} + +namespace PR9507 { + void f(int * const&); // expected-note{{candidate function}} + void f(int const(&)[1]); // expected-note{{candidate function}} + + int main() { + int n[1]; + f(n); // expected-error{{call to 'f' is ambiguous}} + } +} diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 44d013f..462d023 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -33,7 +33,7 @@ struct A { A make_A(); -bool operator==(A&, Z&); // expected-note 2{{candidate function}} +bool operator==(A&, Z&); // expected-note 3{{candidate function}} void h(A a, const A ac, Z z) { make_A() == z; @@ -68,7 +68,7 @@ struct E2 { }; // C++ [over.match.oper]p3 - enum restriction. -float& operator==(E1, E2); +float& operator==(E1, E2); // expected-note{{candidate function}} void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2, Enum1 next_enum1) { float &f1 = (e1 == e2); @@ -85,8 +85,8 @@ class pr5244_foo pr5244_foo(char); }; -bool operator==(const pr5244_foo& s1, const pr5244_foo& s2); -bool operator==(char c, const pr5244_foo& s); +bool operator==(const pr5244_foo& s1, const pr5244_foo& s2); // expected-note{{candidate function}} +bool operator==(char c, const pr5244_foo& s); // expected-note{{candidate function}} enum pr5244_bar { @@ -399,3 +399,12 @@ namespace rdar9136502 { y << x.i; // expected-error{{a bound member function may only be called}} } } + +namespace rdar9222009 { +class StringRef { + inline bool operator==(StringRef LHS, StringRef RHS) { // expected-error{{overloaded 'operator==' must be a binary operator (has 3 parameters)}} + return !(LHS == RHS); // expected-error{{invalid operands to binary expression ('rdar9222009::StringRef' and 'rdar9222009::StringRef')}} + } +}; + +} diff --git a/test/SemaCXX/redeclared-alias-template.cpp b/test/SemaCXX/redeclared-alias-template.cpp new file mode 100644 index 0000000..b368fcf --- /dev/null +++ b/test/SemaCXX/redeclared-alias-template.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +template<typename T> using A = int; // expected-note 2{{previous}} +template<typename T> using A = char; // expected-error {{type alias template redefinition with different types ('char' vs 'int')}} +template<typename T1, typename T2> using A = T1; // expected-error {{too many template parameters in template redeclaration}} + +template<typename T1, typename T2> using B = T1; // expected-note {{previous}} +template<typename T2, typename T1> using B = T1; // expected-error {{type alias template redefinition with different types}} + + +template<typename> struct S; +template<template<typename> class F> using FInt = F<int>; +template<typename X> using SXRInt = FInt<S<X>::template R>; +template<typename X> using SXRInt = typename S<X>::template R<int>; // ok, redeclaration. + +template<template<typename> class> struct TT; + +namespace FilterLookup { + TT<A> f(); // expected-note {{previous declaration is here}} + + template<typename> using A = int; + TT<A> f(); // expected-error {{functions that differ only in their return type cannot be overloaded}} +} diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index f526249..68005a5 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s +// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding -Wundefined-reinterpret-cast %s #include <stdint.h> @@ -116,3 +116,163 @@ namespace PR9564 { __attribute((ext_vector_type(4))) typedef float v4; float& w(v4 &a) { return reinterpret_cast<float&>(a[1]); } // expected-error {{not allowed}} } + +void dereference_reinterpret_cast() { + struct A {}; + typedef A A2; + class B {}; + typedef B B2; + A a; + B b; + A2 a2; + B2 b2; + long l; + double d; + float f; + char c; + unsigned char uc; + void* v_ptr; + (void)reinterpret_cast<double&>(l); // expected-warning {{reinterpret_cast from 'long' to 'double &' has undefined behavior}} + (void)*reinterpret_cast<double*>(&l); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}} + (void)reinterpret_cast<double&>(f); // expected-warning {{reinterpret_cast from 'float' to 'double &' has undefined behavior}} + (void)*reinterpret_cast<double*>(&f); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'float *' has undefined behavior}} + (void)reinterpret_cast<float&>(l); // expected-warning {{reinterpret_cast from 'long' to 'float &' has undefined behavior}} + (void)*reinterpret_cast<float*>(&l); // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'long *' has undefined behavior}} + (void)reinterpret_cast<float&>(d); // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}} + (void)*reinterpret_cast<float*>(&d); // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}} + + // TODO: add warning for tag types + (void)reinterpret_cast<A&>(b); + (void)*reinterpret_cast<A*>(&b); + (void)reinterpret_cast<B&>(a); + (void)*reinterpret_cast<B*>(&a); + (void)reinterpret_cast<A2&>(b2); + (void)*reinterpret_cast<A2*>(&b2); + (void)reinterpret_cast<B2&>(a2); + (void)*reinterpret_cast<B2*>(&a2); + + // Casting to itself is allowed + (void)reinterpret_cast<A&>(a); + (void)*reinterpret_cast<A*>(&a); + (void)reinterpret_cast<B&>(b); + (void)*reinterpret_cast<B*>(&b); + (void)reinterpret_cast<long&>(l); + (void)*reinterpret_cast<long*>(&l); + (void)reinterpret_cast<double&>(d); + (void)*reinterpret_cast<double*>(&d); + (void)reinterpret_cast<char&>(c); + (void)*reinterpret_cast<char*>(&c); + + // Casting to and from chars are allowable + (void)reinterpret_cast<A&>(c); + (void)*reinterpret_cast<A*>(&c); + (void)reinterpret_cast<B&>(c); + (void)*reinterpret_cast<B*>(&c); + (void)reinterpret_cast<long&>(c); + (void)*reinterpret_cast<long*>(&c); + (void)reinterpret_cast<double&>(c); + (void)*reinterpret_cast<double*>(&c); + (void)reinterpret_cast<char&>(l); + (void)*reinterpret_cast<char*>(&l); + (void)reinterpret_cast<char&>(d); + (void)*reinterpret_cast<char*>(&d); + (void)reinterpret_cast<char&>(f); + (void)*reinterpret_cast<char*>(&f); + + // Casting from void pointer. + (void)*reinterpret_cast<A*>(v_ptr); + (void)*reinterpret_cast<B*>(v_ptr); + (void)*reinterpret_cast<long*>(v_ptr); + (void)*reinterpret_cast<double*>(v_ptr); + (void)*reinterpret_cast<float*>(v_ptr); + + // Casting to void pointer + (void)*reinterpret_cast<void*>(&a); + (void)*reinterpret_cast<void*>(&b); + (void)*reinterpret_cast<void*>(&l); + (void)*reinterpret_cast<void*>(&d); + (void)*reinterpret_cast<void*>(&f); +} + +void reinterpret_cast_whitelist () { + // the dynamic type of the object + int a; + float b; + (void)reinterpret_cast<int&>(a); + (void)*reinterpret_cast<int*>(&a); + (void)reinterpret_cast<float&>(b); + (void)*reinterpret_cast<float*>(&b); + + // a cv-qualified version of the dynamic object + (void)reinterpret_cast<const int&>(a); + (void)*reinterpret_cast<const int*>(&a); + (void)reinterpret_cast<volatile int&>(a); + (void)*reinterpret_cast<volatile int*>(&a); + (void)reinterpret_cast<const volatile int&>(a); + (void)*reinterpret_cast<const volatile int*>(&a); + (void)reinterpret_cast<const float&>(b); + (void)*reinterpret_cast<const float*>(&b); + (void)reinterpret_cast<volatile float&>(b); + (void)*reinterpret_cast<volatile float*>(&b); + (void)reinterpret_cast<const volatile float&>(b); + (void)*reinterpret_cast<const volatile float*>(&b); + + // a type that is the signed or unsigned type corresponding to the dynamic + // type of the object + signed d; + unsigned e; + (void)reinterpret_cast<signed&>(d); + (void)*reinterpret_cast<signed*>(&d); + (void)reinterpret_cast<signed&>(e); + (void)*reinterpret_cast<signed*>(&e); + (void)reinterpret_cast<unsigned&>(d); + (void)*reinterpret_cast<unsigned*>(&d); + (void)reinterpret_cast<unsigned&>(e); + (void)*reinterpret_cast<unsigned*>(&e); + + // a type that is the signed or unsigned type corresponding a cv-qualified + // version of the dynamic type the object + (void)reinterpret_cast<const signed&>(d); + (void)*reinterpret_cast<const signed*>(&d); + (void)reinterpret_cast<const signed&>(e); + (void)*reinterpret_cast<const signed*>(&e); + (void)reinterpret_cast<const unsigned&>(d); + (void)*reinterpret_cast<const unsigned*>(&d); + (void)reinterpret_cast<const unsigned&>(e); + (void)*reinterpret_cast<const unsigned*>(&e); + (void)reinterpret_cast<volatile signed&>(d); + (void)*reinterpret_cast<volatile signed*>(&d); + (void)reinterpret_cast<volatile signed&>(e); + (void)*reinterpret_cast<volatile signed*>(&e); + (void)reinterpret_cast<volatile unsigned&>(d); + (void)*reinterpret_cast<volatile unsigned*>(&d); + (void)reinterpret_cast<volatile unsigned&>(e); + (void)*reinterpret_cast<volatile unsigned*>(&e); + (void)reinterpret_cast<const volatile signed&>(d); + (void)*reinterpret_cast<const volatile signed*>(&d); + (void)reinterpret_cast<const volatile signed&>(e); + (void)*reinterpret_cast<const volatile signed*>(&e); + (void)reinterpret_cast<const volatile unsigned&>(d); + (void)*reinterpret_cast<const volatile unsigned*>(&d); + (void)reinterpret_cast<const volatile unsigned&>(e); + (void)*reinterpret_cast<const volatile unsigned*>(&e); + + // an aggregate or union type that includes one of the aforementioned types + // among its members (including, recursively, a member of a subaggregate or + // contained union) + // TODO: checking is not implemented for tag types + + // a type that is a (possible cv-qualified) base class type of the dynamic + // type of the object + // TODO: checking is not implemented for tag types + + // a char or unsigned char type + (void)reinterpret_cast<char&>(a); + (void)*reinterpret_cast<char*>(&a); + (void)reinterpret_cast<unsigned char&>(a); + (void)*reinterpret_cast<unsigned char*>(&a); + (void)reinterpret_cast<char&>(b); + (void)*reinterpret_cast<char*>(&b); + (void)reinterpret_cast<unsigned char&>(b); + (void)*reinterpret_cast<unsigned char*>(&b); +} diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index af7f50c..b457f6a 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -39,6 +39,11 @@ g(); char* const h(); // expected-warning{{'const' type qualifier on return type has no effect}} char* volatile i(); // expected-warning{{'volatile' type qualifier on return type has no effect}} +char* +volatile // expected-warning{{'const volatile' type qualifiers on return type have no effect}} +const +j(); + const volatile int scalar_cv(); // expected-warning{{'const volatile' type qualifiers on return type have no effect}} } @@ -53,3 +58,14 @@ namespace PR9328 { class foo { operator int * const (); }; + +namespace PR10057 { + struct S { + ~S(); + }; + + template <class VarType> + void Test(const VarType& value) { + return S() = value; + } +} diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp index d3d6d79..5c59578 100644 --- a/test/SemaCXX/struct-class-redecl.cpp +++ b/test/SemaCXX/struct-class-redecl.cpp @@ -1,8 +1,164 @@ // RUN: %clang_cc1 -fsyntax-only -Wmismatched-tags -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wmismatched-tags %s 2>&1 | FileCheck %s class X; // expected-note 2{{here}} typedef struct X * X_t; // expected-warning{{previously declared}} +union X { int x; float y; }; // expected-error{{use of 'X' with tag type that does not match previous declaration}} -template<typename T> struct Y; // expected-note{{previous}} +template<typename T> struct Y; // expected-note{{did you mean class here?}} 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}} +class A; +class A; // expected-note{{previous use is here}} +struct A; // expected-warning{{struct 'A' was previously declared as a class}} + +class B; // expected-note{{did you mean struct here?}} +class B; // expected-note{{previous use is here}}\ + // expected-note{{did you mean struct here?}} +struct B; // expected-warning{{struct 'B' was previously declared as a class}} +struct B {}; // expected-warning{{'B' defined as a struct here but previously declared as a class}} + +class C; // expected-note{{previous use is here}} +struct C; // expected-warning{{struct 'C' was previously declared as a class}}\ + // expected-note{{previous use is here}}\ + // expected-note{{did you mean class here?}} +class C; // expected-warning{{class 'C' was previously declared as a struct}}\ + // expected-note{{previous use is here}} +struct C; // expected-warning{{struct 'C' was previously declared as a class}}\ + // expected-note{{did you mean class here?}} +class C {}; // expected-warning{{'C' defined as a class here but previously declared as a struct}} + +struct D {}; // expected-note{{previous definition is here}}\ + // expected-note{{previous use is here}} +class D {}; // expected-error{{redefinition of 'D'}} +struct D; +class D; // expected-warning{{class 'D' was previously declared as a struct}}\ + // expected-note{{did you mean struct here?}} + +class E; +class E; +class E {}; +class E; + +struct F; +struct F; +struct F {}; +struct F; + +template<class U> class G; // expected-note{{previous use is here}}\ + // expected-note{{did you mean struct here?}} +template<class U> struct G; // expected-warning{{struct template 'G' was previously declared as a class template}} +template<class U> struct G {}; // expected-warning{{'G' defined as a struct template here but previously declared as a class template}} + +/* +*** 'X' messages *** +CHECK: warning: struct 'X' was previously declared as a class +CHECK: {{^}}typedef struct X * X_t; +CHECK: {{^}} ^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class X; +CHECK: {{^}} ^{{$}} +CHECK: error: use of 'X' with tag type that does not match previous declaration +CHECK: {{^}}union X { int x; float y; }; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}class{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class X; +CHECK: {{^}} ^{{$}} +*** 'Y' messages *** +CHECK: warning: 'Y' defined as a class template here but + previously declared as a struct template +CHECK: {{^}}template<class U> class Y { }; +CHECK: {{^}} ^{{$}} +CHECK: note: did you mean class here? +CHECK: {{^}}template<typename T> struct Y; +CHECK: {{^}} ^~~~~~{{$}} +CHECK: {{^}} class{{$}} +*** 'A' messages *** +CHECK: warning: struct 'A' was previously declared as a class +CHECK: {{^}}struct A; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class A; +CHECK: {{^}} ^{{$}} +*** 'B' messages *** +CHECK: warning: struct 'B' was previously declared as a class +CHECK: {{^}}struct B; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class B; +CHECK: {{^}} ^{{$}} +CHECK: 'B' defined as a struct here but previously declared as a class +CHECK: {{^}}struct B {}; +CHECK: {{^}}^{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}class B; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}struct{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}class B; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}struct{{$}} +*** 'C' messages *** +CHECK: warning: struct 'C' was previously declared as a class +CHECK: {{^}}struct C; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class C; +CHECK: {{^}} ^{{$}} +CHECK: warning: class 'C' was previously declared as a struct +CHECK: {{^}}class C; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}struct C; +CHECK: {{^}} ^{{$}} +CHECK: warning: struct 'C' was previously declared as a class +CHECK: {{^}}struct C; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}class C; +CHECK: {{^}} ^{{$}} +CHECK: warning: 'C' defined as a class here but previously declared as a struct +CHECK: {{^}}class C {}; +CHECK: {{^}}^{{$}} +CHECK: note: did you mean class here? +CHECK: {{^}}struct C; +CHECK: {{^}}^~~~~~{{$}} +CHECK: {{^}}class{{$}} +CHECK: note: did you mean class here? +CHECK: {{^}}struct C; +CHECK: {{^}}^~~~~~{{$}} +CHECK: {{^}}class{{$}} +*** 'D' messages *** +CHECK: error: redefinition of 'D' +CHECK: {{^}}class D {}; +CHECK: {{^}} ^{{$}} +CHECK: note: previous definition is here +CHECK: {{^}}struct D {}; +CHECK: {{^}} ^{{$}} +CHECK: warning: class 'D' was previously declared as a struct +CHECK: {{^}}class D; +CHECK: {{^}}^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}struct D {}; +CHECK: {{^}} ^{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}class D; +CHECK: {{^}}^~~~~{{$}} +CHECK: {{^}}struct{{$}} +*** 'E' messages *** +*** 'F' messages *** +*** 'G' messages *** +CHECK: warning: struct template 'G' was previously declared as a class template +CHECK: {{^}}template<class U> struct G; +CHECK: {{^}} ^{{$}} +CHECK: note: previous use is here +CHECK: {{^}}template<class U> class G; +CHECK: {{^}} ^{{$}} +CHECK: warning: 'G' defined as a struct template here but previously declared as a class template +CHECK: {{^}}template<class U> struct G {}; +CHECK: {{^}} ^{{$}} +CHECK: note: did you mean struct here? +CHECK: {{^}}template<class U> class G; +CHECK: {{^}} ^~~~~ +CHECK: {{^}} struct +*/ diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp index 3882a1f..8a8cf33 100644 --- a/test/SemaCXX/switch.cpp +++ b/test/SemaCXX/switch.cpp @@ -8,7 +8,7 @@ void test() { } int n = 3; - switch (n && 1) { // expected-warning {{bool}} + switch (n && true) { // expected-warning {{bool}} case 1: break; } diff --git a/test/SemaCXX/tag-ambig.cpp b/test/SemaCXX/tag-ambig.cpp new file mode 100644 index 0000000..6403cf3 --- /dev/null +++ b/test/SemaCXX/tag-ambig.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/9168556> +typedef struct Point Point; + +namespace NameSpace { + class Point; +} + +using namespace NameSpace; + +class Test +{ +public: + struct Point { }; + virtual bool testMethod (Test::Point& p) = 0; +}; + +// PR8151 +namespace A { struct Face {}; } +namespace B { struct Face {}; } +using namespace A; +using namespace B; + +class C { + struct Face; + Face *mFaces; +}; diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 96e9696..30cc6a3 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++0x %s #define T(b) (b) ? 1 : -1 #define F(b) (b) ? -1 : 1 @@ -38,8 +38,7 @@ typedef Derives DerivesArNB[]; struct DerivesEmpty : Empty {}; struct HasCons { HasCons(int); }; struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); }; -struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; // \ - // expected-warning {{rvalue references}} +struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; struct HasDest { ~HasDest(); }; class HasPriv { int priv; }; class HasProt { protected: int prot; }; @@ -870,6 +869,15 @@ struct NonTrivialStruct { } }; +struct SuperNonTrivialStruct { + SuperNonTrivialStruct() { } + ~SuperNonTrivialStruct() { } +}; + +struct NonTCStruct { + NonTCStruct(const NonTCStruct&) {} +}; + void is_trivial2() { int t01[T(__is_trivial(char))]; @@ -897,6 +905,39 @@ void is_trivial2() int t30[F(__is_trivial(void))]; int t31[F(__is_trivial(NonTrivialStruct))]; + int t32[F(__is_trivial(SuperNonTrivialStruct))]; + int t33[F(__is_trivial(NonTCStruct))]; +} + +void is_trivially_copyable2() +{ + int t01[T(__is_trivially_copyable(char))]; + int t02[T(__is_trivially_copyable(int))]; + int t03[T(__is_trivially_copyable(long))]; + int t04[T(__is_trivially_copyable(short))]; + int t05[T(__is_trivially_copyable(signed char))]; + int t06[T(__is_trivially_copyable(wchar_t))]; + int t07[T(__is_trivially_copyable(bool))]; + int t08[T(__is_trivially_copyable(float))]; + int t09[T(__is_trivially_copyable(double))]; + int t10[T(__is_trivially_copyable(long double))]; + int t11[T(__is_trivially_copyable(unsigned char))]; + int t12[T(__is_trivially_copyable(unsigned int))]; + int t13[T(__is_trivially_copyable(unsigned long long))]; + int t14[T(__is_trivially_copyable(unsigned long))]; + int t15[T(__is_trivially_copyable(unsigned short))]; + int t16[T(__is_trivially_copyable(ClassType))]; + int t17[T(__is_trivially_copyable(Derives))]; + int t18[T(__is_trivially_copyable(Enum))]; + int t19[T(__is_trivially_copyable(IntAr))]; + int t20[T(__is_trivially_copyable(Union))]; + int t21[T(__is_trivially_copyable(UnionAr))]; + int t22[T(__is_trivially_copyable(TrivialStruct))]; + int t23[T(__is_trivially_copyable(NonTrivialStruct))]; + + int t30[F(__is_trivially_copyable(void))]; + int t32[F(__is_trivially_copyable(SuperNonTrivialStruct))]; + int t31[F(__is_trivially_copyable(NonTCStruct))]; } struct CStruct { @@ -1027,7 +1068,7 @@ struct HasCopy { }; struct HasMove { - HasMove(HasMove&& cp); // expected-warning {{rvalue references}} + HasMove(HasMove&& cp); }; struct HasTemplateCons { @@ -1211,6 +1252,9 @@ void has_nothrow_copy() { { int arr[F(__has_nothrow_copy(cvoid))]; } } +template<bool b> struct assert_expr; +template<> struct assert_expr<true> {}; + void has_nothrow_constructor() { { int arr[T(__has_nothrow_constructor(Int))]; } { int arr[T(__has_nothrow_constructor(IntAr))]; } @@ -1238,6 +1282,11 @@ void has_nothrow_constructor() { { int arr[F(__has_nothrow_constructor(void))]; } { int arr[F(__has_nothrow_constructor(cvoid))]; } { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; } + + // While parsing an in-class initializer, the constructor is not known to be + // non-throwing yet. + struct HasInClassInit { int n = (assert_expr<!__has_nothrow_constructor(HasInClassInit)>(), 0); }; + { int arr[T(__has_nothrow_constructor(HasInClassInit))]; } } void has_virtual_destructor() { @@ -1474,6 +1523,51 @@ void is_trivial() { int arr[F(__is_trivial(cvoid))]; } } +void is_trivially_copyable() +{ + { int arr[T(__is_trivially_copyable(int))]; } + { int arr[T(__is_trivially_copyable(Enum))]; } + { int arr[T(__is_trivially_copyable(POD))]; } + { int arr[T(__is_trivially_copyable(Int))]; } + { int arr[T(__is_trivially_copyable(IntAr))]; } + { int arr[T(__is_trivially_copyable(IntArNB))]; } + { int arr[T(__is_trivially_copyable(Statics))]; } + { int arr[T(__is_trivially_copyable(Empty))]; } + { int arr[T(__is_trivially_copyable(EmptyUnion))]; } + { int arr[T(__is_trivially_copyable(Union))]; } + { int arr[T(__is_trivially_copyable(Derives))]; } + { int arr[T(__is_trivially_copyable(DerivesAr))]; } + { int arr[T(__is_trivially_copyable(DerivesArNB))]; } + { int arr[T(__is_trivially_copyable(DerivesEmpty))]; } + { int arr[T(__is_trivially_copyable(HasFunc))]; } + { int arr[T(__is_trivially_copyable(HasOp))]; } + { int arr[T(__is_trivially_copyable(HasConv))]; } + { int arr[T(__is_trivially_copyable(HasAssign))]; } + { int arr[T(__is_trivially_copyable(HasAnonymousUnion))]; } + { int arr[T(__is_trivially_copyable(HasPriv))]; } + { int arr[T(__is_trivially_copyable(HasProt))]; } + { int arr[T(__is_trivially_copyable(DerivesHasPriv))]; } + { int arr[T(__is_trivially_copyable(DerivesHasProt))]; } + { int arr[T(__is_trivially_copyable(Vector))]; } + { int arr[T(__is_trivially_copyable(VectorExt))]; } + { int arr[T(__is_trivially_copyable(HasCons))]; } + { int arr[T(__is_trivially_copyable(HasRef))]; } + { int arr[T(__is_trivially_copyable(HasNonPOD))]; } + { int arr[T(__is_trivially_copyable(DerivesHasCons))]; } + { int arr[T(__is_trivially_copyable(DerivesHasRef))]; } + + { int arr[F(__is_trivially_copyable(HasCopyAssign))]; } + { int arr[F(__is_trivially_copyable(HasMoveAssign))]; } + { int arr[F(__is_trivially_copyable(HasDest))]; } + { int arr[F(__is_trivially_copyable(HasVirt))]; } + { int arr[F(__is_trivially_copyable(DerivesHasCopyAssign))]; } + { int arr[F(__is_trivially_copyable(DerivesHasMoveAssign))]; } + { int arr[F(__is_trivially_copyable(DerivesHasDest))]; } + { int arr[F(__is_trivially_copyable(DerivesHasVirt))]; } + { int arr[F(__is_trivially_copyable(void))]; } + { int arr[F(__is_trivially_copyable(cvoid))]; } +} + void array_rank() { int t01[T(__array_rank(IntAr) == 1)]; int t02[T(__array_rank(ConstIntArAr) == 2)]; diff --git a/test/SemaCXX/underlying_type.cpp b/test/SemaCXX/underlying_type.cpp new file mode 100644 index 0000000..607d9ad --- /dev/null +++ b/test/SemaCXX/underlying_type.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -ffreestanding -fsyntax-only -verify -std=c++0x %s + +#include "limits.h" + +template<typename T, typename U> +struct is_same_type { + static const bool value = false; +}; +template <typename T> +struct is_same_type<T, T> { + static const bool value = true; +}; + +__underlying_type(int) a; // expected-error {{only enumeration types}} +__underlying_type(struct b) c; // expected-error {{only enumeration types}} + +enum class f : char; +static_assert(is_same_type<char, __underlying_type(f)>::value, + "f has the wrong underlying type"); + +enum g {d = INT_MIN }; +static_assert(is_same_type<int, __underlying_type(g)>::value, + "g has the wrong underlying type"); + +__underlying_type(f) h; +static_assert(is_same_type<char, decltype(h)>::value, + "h has the wrong type"); + +template <typename T> +struct underlying_type { + typedef __underlying_type(T) type; // expected-error {{only enumeration types}} +}; + +static_assert(is_same_type<underlying_type<f>::type, char>::value, + "f has the wrong underlying type in the template"); + +underlying_type<int>::type e; // expected-note {{requested here}} diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp index 10520fb..dfe0f46 100644 --- a/test/SemaCXX/value-initialization.cpp +++ b/test/SemaCXX/value-initialization.cpp @@ -1,12 +1,11 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x -struct A { // expected-error {{implicit default constructor for 'A' must explicitly initialize the const member 'i'}} \ - // expected-warning{{struct 'A' does not declare any constructor to initialize its non-modifiable members}} - const int i; // expected-note {{declared here}} \ - // expected-note{{const member 'i' will never be initialized}} +struct A { //expected-note {{marked deleted here}} \ + // expected-warning {{does not declare any constructor to initialize}} + const int i; // expected-note{{const member 'i' will never be initialized}} virtual void f() { } }; int main () { - (void)A(); // expected-note {{first required here}} + (void)A(); // expected-error {{call to deleted constructor}} } diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index 55ec941..df0080f 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -56,15 +56,18 @@ void t4() } class E { - E(int, ...); + E(int, ...); // expected-note 2{{implicitly declared private here}} }; void t5() { C c(10); - E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} - (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} + E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \ + // expected-error{{calling a private constructor of class 'E'}} + (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \ + // expected-error{{calling a private constructor of class 'E'}} + } // PR5761: unevaluated operands and the non-POD warning diff --git a/test/SemaCXX/vtable-instantiation.cc b/test/SemaCXX/vtable-instantiation.cc index 49949a7..2a1b989 100644 --- a/test/SemaCXX/vtable-instantiation.cc +++ b/test/SemaCXX/vtable-instantiation.cc @@ -1,21 +1,22 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// PR8640 -template<class T1> struct C1 { - virtual void c1() { - T1 t1 = 3; // expected-error {{cannot initialize a variable}} - } -}; +namespace PR8640 { + template<class T1> struct C1 { + virtual void c1() { + T1 t1 = 3; // expected-error {{cannot initialize a variable}} + } + }; -template<class T2> struct C2 { - void c2() { - new C1<T2>(); // expected-note {{in instantiation of member function}} - } -}; + template<class T2> struct C2 { + void c2() { + new C1<T2>(); // expected-note {{in instantiation of member function}} + } + }; -void f() { - C2<int*> c2; - c2.c2(); // expected-note {{in instantiation of member function}} + void f() { + C2<int*> c2; + c2.c2(); // expected-note {{in instantiation of member function}} + } } namespace PR9325 { @@ -42,5 +43,26 @@ namespace PR9325 { { Target<int*>* traits = &Provider<int*>::Instance; } +} +namespace PR10020 { + struct MG { + virtual void Accept(int) = 0; + }; + + template <typename Type> + struct GMG : MG { + void Accept(int i) { + static_cast<Type *>(0)->Accept(i); // expected-error{{member reference base}} + } + static GMG* Method() { return &singleton; } // expected-note{{in instantiation of}} + static GMG singleton; + }; + + template <typename Type> + GMG<Type> GMG<Type>::singleton; + + void test(void) { + GMG<int>::Method(); // expected-note{{in instantiation of}} + } } diff --git a/test/SemaCXX/warn-bad-memaccess.cpp b/test/SemaCXX/warn-bad-memaccess.cpp new file mode 100644 index 0000000..e7d095f --- /dev/null +++ b/test/SemaCXX/warn-bad-memaccess.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -Wdynamic-class-memaccess -verify %s + +extern "C" void *memset(void *, int, unsigned); +extern "C" void *memmove(void *s1, const void *s2, unsigned n); +extern "C" void *memcpy(void *s1, const void *s2, unsigned n); + +// Several types that should not warn. +struct S1 {} s1; +struct S2 { int x; } s2; +struct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3; + +class C1 { + int x, y, z; +public: + void foo() {} +} c1; + +struct X1 { virtual void f(); } x1; +struct X2 : virtual S1 {} x2; + +void test_warn() { + memset(&x1, 0, sizeof x1); // \ + // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + memset(&x2, 0, sizeof x2); // \ + // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + + memmove(&x1, 0, sizeof x1); // \ + // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + memmove(0, &x1, sizeof x1); // \ + // expected-warning{{source of this 'memmove' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + memcpy(&x1, 0, sizeof x1); // \ + // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + memcpy(0, &x1, sizeof x1); // \ + // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} +} + +void test_nowarn(void *void_ptr) { + int i, *iptr; + float y; + char c; + + memset(&i, 0, sizeof i); + memset(&iptr, 0, sizeof iptr); + memset(&y, 0, sizeof y); + memset(&c, 0, sizeof c); + memset(void_ptr, 0, 42); + memset(&s1, 0, sizeof s1); + memset(&s2, 0, sizeof s2); + memset(&s3, 0, sizeof s3); + memset(&c1, 0, sizeof c1); + + // Unevaluated code shouldn't warn. + (void)sizeof memset(&x1, 0, sizeof x1); + + // Dead code shouldn't warn. + if (false) memset(&x1, 0, sizeof x1); +} + +namespace N { + void *memset(void *, int, unsigned); + void test_nowarn() { + N::memset(&x1, 0, sizeof x1); + } +} diff --git a/test/SemaCXX/warn-non-pod-memset.cpp b/test/SemaCXX/warn-non-pod-memset.cpp deleted file mode 100644 index fbdcead..0000000 --- a/test/SemaCXX/warn-non-pod-memset.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -Wnon-pod-memset -verify %s - -extern void *memset(void *, int, unsigned); - -// Several POD types that should not warn. -struct S1 {} s1; -struct S2 { int x; } s2; -struct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3; - -// We use the C++11 concept of POD for this warning, so ensure a non-aggregate -// still warns. -class C1 { - int x, y, z; -public: - void foo() {} -} c1; - -// Non-POD types that should warn. -struct X1 { X1(); } x1; -struct X2 { ~X2(); } x2; -struct X3 { virtual void f(); } x3; -struct X4 : X2 {} x4; -struct X5 : virtual S1 {} x5; - -void test_warn() { - memset(&x1, 0, sizeof x1); // \ - // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \ - // expected-note {{explicitly cast the pointer to silence this warning}} - memset(&x2, 0, sizeof x2); // \ - // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \ - // expected-note {{explicitly cast the pointer to silence this warning}} - memset(&x3, 0, sizeof x3); // \ - // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \ - // expected-note {{explicitly cast the pointer to silence this warning}} - memset(&x4, 0, sizeof x4); // \ - // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \ - // expected-note {{explicitly cast the pointer to silence this warning}} - memset(&x5, 0, sizeof x5); // \ - // expected-warning {{destination for this memset call is a pointer to a non-POD type}} \ - // expected-note {{explicitly cast the pointer to silence this warning}} -} - -void test_nowarn(void *void_ptr) { - int i, *iptr; - float y; - char c; - - memset(&i, 0, sizeof i); - memset(&iptr, 0, sizeof iptr); - memset(&y, 0, sizeof y); - memset(&c, 0, sizeof c); - memset(void_ptr, 0, 42); - memset(&s1, 0, sizeof s1); - memset(&s2, 0, sizeof s2); - memset(&s3, 0, sizeof s3); - memset(&c1, 0, sizeof c1); - - // Unevaluated code shouldn't warn. - (void)sizeof memset(&x1, 0, sizeof x1); - - // Dead code shouldn't warn. - if (false) memset(&x1, 0, sizeof x1); -} diff --git a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp new file mode 100644 index 0000000..698eccd --- /dev/null +++ b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +struct A { + A() { f(); } // expected-warning {{call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the constructor of 'A'}} + ~A() { f(); } // expected-warning {{call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the destructor of 'A'}} + + virtual void f() = 0; // expected-note 2 {{'f' declared here}} +}; |