diff options
Diffstat (limited to 'test/SemaCXX')
178 files changed, 7498 insertions, 862 deletions
diff --git a/test/SemaCXX/Inputs/array-bounds-system-header.h b/test/SemaCXX/Inputs/array-bounds-system-header.h new file mode 100644 index 0000000..07cde80 --- /dev/null +++ b/test/SemaCXX/Inputs/array-bounds-system-header.h @@ -0,0 +1,11 @@ +// "System header" for testing that -Warray-bounds is properly suppressed in +// certain cases. + +#define BAD_MACRO_1 \ + int i[3]; \ + i[3] = 5 +#define BAD_MACRO_2(_b, _i) \ + (_b)[(_i)] = 5 +#define QUESTIONABLE_MACRO(_a) \ + sizeof(_a) > 3 ? (_a)[3] = 5 : 5 +#define NOP(x) (x) diff --git a/test/SemaCXX/Inputs/warn-new-overaligned-3.h b/test/SemaCXX/Inputs/warn-new-overaligned-3.h new file mode 100644 index 0000000..d2bd4d5 --- /dev/null +++ b/test/SemaCXX/Inputs/warn-new-overaligned-3.h @@ -0,0 +1,19 @@ +#pragma GCC system_header + +// This header file pretends to be <new> from the system library, for the +// purpose of the over-aligned warnings test. + +void* operator new(unsigned long) { + return 0; +} +void* operator new[](unsigned long) { + return 0; +} + +void* operator new(unsigned long, void *) { + return 0; +} + +void* operator new[](unsigned long, void *) { + return 0; +} diff --git a/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp b/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp new file mode 100644 index 0000000..0c7d354 --- /dev/null +++ b/test/SemaCXX/MicrosoftCompatibility-cxx98.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++98 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions + + +//MSVC allows forward enum declaration +enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}} +ENUM *var = 0; +ENUM var2 = (ENUM)3; +enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}} diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp index dfc47d6..3634fa3 100644 --- a/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -std=c++11 -Wmicrosoft -verify -fms-compatibility -fexceptions -fcxx-exceptions @@ -23,7 +23,7 @@ namespace ms_protected_scope { int jump_over_variable_init(bool b) { if (b) - goto foo; // expected-warning {{illegal goto into protected scope}} + goto foo; // expected-warning {{goto into protected scope}} C c; // expected-note {{jump bypasses variable initialization}} foo: return 1; @@ -35,7 +35,7 @@ struct Y { void jump_over_var_with_dtor() { goto end; // expected-warning{{goto into protected scope}} - Y y; // expected-note {{jump bypasses variable initialization}} + Y y; // expected-note {{jump bypasses variable with a non-trivial destructor}} end: ; } @@ -51,7 +51,7 @@ void jump_over_var_with_dtor() { void exception_jump() { - goto l2; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{goto into protected scope}} try { // expected-note {{jump bypasses initialization of try block}} l2: ; } catch(int) { @@ -68,91 +68,109 @@ int jump_over_indirect_goto() { } +namespace PR11826 { + struct pair { + pair(int v) { } + void operator=(pair&& rhs) { } + }; + void f() { + pair p0(3); + pair p = p0; + } +} + +namespace PR11826_for_symmetry { + struct pair { + pair(int v) { } + pair(pair&& rhs) { } + }; + void f() { + pair p0(3); + pair p(4); + p = p0; + } +} + +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 referring to inaccessible member 'ms_using_declaration_bug::B::f' (which refers to accessible member 'ms_using_declaration_bug::A::f') is a Microsoft compatibility extension}} +}; + +} + + +namespace MissingTypename { + +template<class T> class A { +public: + typedef int TYPE; +}; + +template<class T> class B { +public: + typedef int TYPE; +}; -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 MissingTypename {
-
-template<class T> class A {
-public:
- typedef int TYPE;
-};
-
-template<class T> class B {
-public:
- typedef int TYPE;
-};
-
-
-template<class T, class U>
-class C : private A<T>, public B<U> {
-public:
- typedef A<T> Base1;
- typedef B<U> Base2;
- typedef A<U> Base3;
-
- A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}}
- Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}}
-
- B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}}
- Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}}
-
- A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}}
- Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}}
- };
-
-class D {
-public:
- typedef int Type;
-};
-
-template <class T>
-void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}}
-{
- const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}}
-}
-
-template void function_missing_typename<D>(const D::Type param);
-
-}
-
-
-
-namespace lookup_dependent_bases_id_expr {
-
-template<class T> class A {
-public:
- int var;
-};
-
-
-template<class T>
-class B : public A<T> {
-public:
- void f() {
- var = 3;
- }
-};
-
-template class B<int>;
-
-}
\ No newline at end of file +template<class T, class U> +class C : private A<T>, public B<U> { +public: + typedef A<T> Base1; + typedef B<U> Base2; + typedef A<U> Base3; + + A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}} + Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}} + + B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}} + Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}} + + A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}} + Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}} + }; + +class D { +public: + typedef int Type; +}; + +template <class T> +void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}} +{ + const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}} +} + +template void function_missing_typename<D>(const D::Type param); + +} + +enum ENUM2 { + ENUM2_a = (enum ENUM2) 4, + ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}} + ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}} +}; + + +namespace PR11791 { + template<class _Ty> + void del(_Ty *_Ptr) { + _Ptr->~_Ty(); // expected-warning {{pseudo-destructors on type void are a Microsoft extension}} + } + + void f() { + int* a = 0; + del((void*)a); // expected-note {{in instantiation of function template specialization}} + } +} diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 63e058b..0b72cd3 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -92,18 +92,8 @@ void m1() { h1(&M::subtractP); } -//MSVC allows forward enum declaration -enum ENUM; // expected-warning {{forward references to 'enum' types are a Microsoft extension}} -ENUM *var = 0; -ENUM var2 = (ENUM)3; -enum ENUM1* var3 = 0;// expected-warning {{forward references to 'enum' types are a Microsoft extension}} -enum ENUM2 { - ENUM2_a = (enum ENUM2) 4, - ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}} - ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}} -}; void f(long long); @@ -203,3 +193,13 @@ void f() } +struct PR11150 { + class X { + virtual void f() = 0; + }; + + int array[__is_abstract(X)? 1 : -1]; +}; + +void f() { int __except = 0; } + diff --git a/test/SemaCXX/PR10177.cpp b/test/SemaCXX/PR10177.cpp new file mode 100644 index 0000000..8d745de --- /dev/null +++ b/test/SemaCXX/PR10177.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T, typename U, U> using alias_ref = T; +template<typename T, typename U, U> void func_ref() {} +template<typename T, typename U, U> struct class_ref {}; + +template<int N> +struct U { + static int a; +}; + +template<int N> struct S; // expected-note 2{{here}} + +template<int N> +int U<N>::a = S<N>::kError; // expected-error 2{{undefined}} + +template<typename T> +void f() { + // FIXME: The standard suggests that U<0>::a is odr-used by this expression, + // but it's not entirely clear that's the right behaviour. + (void)alias_ref<int, int&, U<0>::a>(); + (void)func_ref<int, int&, U<1>::a>(); // expected-note {{here}} + (void)class_ref<int, int&, U<2>::a>(); // expected-note {{here}} +}; + +int main() { + f<int>(); // expected-note 2{{here}} +} + +namespace N { + template<typename T> struct S { static int n; }; + template<typename T> int S<T>::n = 5; + void g(int*); + template<typename T> int f() { + int k[S<T>::n]; + g(k); + return k[3]; + } + int j = f<int>(); +} diff --git a/test/SemaCXX/PR10447.cpp b/test/SemaCXX/PR10447.cpp new file mode 100644 index 0000000..08644ad --- /dev/null +++ b/test/SemaCXX/PR10447.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -verify %s + +// PR12223 +namespace test1 { + namespace N { + extern "C" void f(struct S*); + void g(S*); + } + namespace N { + void f(struct S *s) { + g(s); + } + } +} + +// PR10447 +namespace test2 { + extern "C" { + void f(struct Bar*) { } + test2::Bar *ptr; + } +} diff --git a/test/SemaCXX/PR11358.cpp b/test/SemaCXX/PR11358.cpp new file mode 100644 index 0000000..9c49227 --- /dev/null +++ b/test/SemaCXX/PR11358.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -verify +// PR11358 + +namespace test1 { + template<typename T> + struct container { + class iterator {}; + iterator begin() { return iterator(); } + }; + + template<typename T> + struct Test { + typedef container<T> Container; + void test() { + Container::iterator i = c.begin(); // expected-error{{missing 'typename'}} + } + Container c; + }; +} + +namespace test2 { + template <typename Key, typename Value> + class hash_map { + class const_iterator { void operator++(); }; + const_iterator begin() const; + const_iterator end() const; + }; + + template <typename KeyType, typename ValueType> + void MapTest(hash_map<KeyType, ValueType> map) { + for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); // expected-error{{missing 'typename'}} + it != map.end(); it++) { + } + } +} + +namespace test3 { + template<typename T> + struct container { + class iterator {}; + }; + + template<typename T> + struct Test { + typedef container<T> Container; + void test() { + Container::iterator const i; // expected-error{{missing 'typename'}} + } + Container c; + }; +} diff --git a/test/SemaCXX/PR12481.cpp b/test/SemaCXX/PR12481.cpp new file mode 100644 index 0000000..9487e4d --- /dev/null +++ b/test/SemaCXX/PR12481.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -x c++ -fsyntax-only %s + +class C1 { }; +class C2 { }; +template<class TrieData> struct BinaryTrie { + ~BinaryTrie() { + (void)(({ + static int x = 5; + } + )); + } +}; +class FooTable { + BinaryTrie<C1> c1_trie_; + BinaryTrie<C2> c2_trie_; +}; +FooTable* foo = new FooTable; diff --git a/test/SemaCXX/PR8385.cpp b/test/SemaCXX/PR8385.cpp new file mode 100644 index 0000000..77a117a --- /dev/null +++ b/test/SemaCXX/PR8385.cpp @@ -0,0 +1,7 @@ +// RUN: not %clang_cc1 -fsyntax-only %s + +// don't crash on this, but don't constrain our diagnostics here as they're +// currently rather poor (we even accept things like "template struct {}"). +// Other, explicit tests, should verify the relevant behavior of template +// instantiation. +struct{template struct{ diff --git a/test/SemaCXX/PR9460.cpp b/test/SemaCXX/PR9460.cpp index 2cc435e..0dd8446 100644 --- a/test/SemaCXX/PR9460.cpp +++ b/test/SemaCXX/PR9460.cpp @@ -8,11 +8,11 @@ struct basic_string{ basic_string(aT*); }; -struct runtime_error{ // expected-note {{candidate constructor}} - runtime_error( // expected-note {{candidate constructor}} +struct runtime_error{ + runtime_error( basic_string<char> struct{ // expected-error {{cannot combine with previous 'type-name' declaration specifier}} a(){ // expected-error {{requires a type specifier}} - runtime_error(0); // expected-error {{no matching conversion}} + runtime_error(0); } } ); diff --git a/test/SemaCXX/PR9461.cpp b/test/SemaCXX/PR9461.cpp index ce17931..beed348 100644 --- a/test/SemaCXX/PR9461.cpp +++ b/test/SemaCXX/PR9461.cpp @@ -26,7 +26,7 @@ basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT*,const _Alloc&) :us(_S_construct) {string a;} -struct runtime_error{runtime_error(string);}; // expected-note 2 {{candidate constructor}} +struct runtime_error{runtime_error(string);}; -struct system_error:runtime_error{ // expected-note {{to match}} expected-note {{specified here}} -system_error():time_error("" // expected-error 4 {{expected}} expected-error {{initializer}} expected-note {{to match}} expected-error {{no matching constructor}} +struct system_error:runtime_error{ // expected-note {{to match}} +system_error():time_error("" // expected-error 3 {{expected}} expected-note {{to match}} diff --git a/test/SemaCXX/PR9572.cpp b/test/SemaCXX/PR9572.cpp index b0bbfa6..b475b57 100644 --- a/test/SemaCXX/PR9572.cpp +++ b/test/SemaCXX/PR9572.cpp @@ -3,7 +3,7 @@ class Base { virtual ~Base(); // expected-note {{implicitly declared private here}} }; struct Foo : public Base { // expected-error {{base class 'Base' has private destructor}} - const int kBlah = 3; // expected-warning {{accepted as a C++11 extension}} + const int kBlah = 3; // expected-warning {{is a C++11 extension}} Foo(); }; struct Bar : public Foo { diff --git a/test/SemaCXX/__null.cpp b/test/SemaCXX/__null.cpp index 1989a45..56e59c0 100644 --- a/test/SemaCXX/__null.cpp +++ b/test/SemaCXX/__null.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -// RUN: %clang_cc1 -triple i686-unknown-unknown %s -fsyntax-only -verify +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -Wno-null-conversion -fsyntax-only -verify +// RUN: %clang_cc1 -triple i686-unknown-unknown %s -Wno-null-conversion -fsyntax-only -verify void f() { int* i = __null; diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index 6115ff6..18ad301 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -28,7 +28,7 @@ namespace test1 { private: class X; // expected-note {{previously declared 'private' here}} public: - class X; // expected-error {{ 'X' redeclared with 'public' access}} + class X; // expected-error {{'X' redeclared with 'public' access}} class X {}; }; } diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp index a36fd58..096f748 100644 --- a/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -13,9 +13,9 @@ int (*pfe)(...) = &f; // expected-error{{address of overloaded function 'f' d 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)(int)); // expected-note{{candidate function}} void g(int (*fp)(float)); -void g(int (*fp)(double)); // expected-note{{note: candidate function}} +void g(int (*fp)(double)); // expected-note{{candidate function}} int g1(int); int g1(char); @@ -29,7 +29,7 @@ int g3(char); void g_test() { g(g1); - g(g2); // expected-error{{call to 'g' is ambiguous; candidates are:}} + g(g2); // expected-error{{call to 'g' is ambiguous}} g(g3); } @@ -57,8 +57,7 @@ struct B struct C { C &getC() { - // FIXME: this error message is terrible - return makeAC; // expected-error{{cannot bind to a value of unrelated type}} + return makeAC; // expected-error{{reference to non-static member function must be called}} } C &makeAC(); @@ -99,8 +98,10 @@ namespace PR7971 { } namespace PR8033 { - template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note 2{{candidate function [with T1 = const int, T2 = int]}} - template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note 2{{candidate function [with T1 = int, T2 = const int]}} + template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note {{candidate function [with T1 = const int, T2 = int]}} \ + // expected-note{{candidate function}} + template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note {{candidate function [with T1 = int, T2 = const int]}} \ + // expected-note{{candidate function}} int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} \ // expected-error{{address of overloaded function 'f' is ambiguous}} @@ -146,3 +147,64 @@ namespace PR7425 { bar2(); } } + +namespace test1 { + void fun(int x) {} + + void parameter_number() { + void (*ptr1)(int, int) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(int, int)' with an rvalue of type 'void (*)(int)': different number of parameters (2 vs 1)}} + void (*ptr2)(int, int); + ptr2 = &fun; // expected-error {{assigning to 'void (*)(int, int)' from incompatible type 'void (*)(int)': different number of parameters (2 vs 1)}} + } + + void parameter_mismatch() { + void (*ptr1)(double) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(double)' with an rvalue of type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} + void (*ptr2)(double); + ptr2 = &fun; // expected-error {{assigning to 'void (*)(double)' from incompatible type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} + } + + void return_type_test() { + int (*ptr1)(int) = &fun; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an rvalue of type 'void (*)(int)': different return type ('int' vs 'void')}} + int (*ptr2)(int); + ptr2 = &fun; // expected-error {{assigning to 'int (*)(int)' from incompatible type 'void (*)(int)': different return type ('int' vs 'void')}} + } + + int foo(double x, double y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} + int foo(int x, int y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} + int foo(double x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'double')}} + double foo(float x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} + double foo(int x, float y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}} + double foo(float x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'float')}} + double foo(int x) {return 0;} // expected-note {{candidate function has different return type ('int' expected but has 'double')}} + + int (*ptr)(int) = &foo; // expected-error {{address of overloaded function 'foo' does not match required type 'int (int)'}} + + struct Qualifiers { + void N() {}; + void C() const {}; + void V() volatile {}; + void R() __restrict {}; + void CV() const volatile {}; + void CR() const __restrict {}; + void VR() volatile __restrict {}; + void CVR() const volatile __restrict {}; + }; + + + void QualifierTest() { + void (Qualifiers::*X)(); + X = &Qualifiers::C; // expected-error {{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const': different qualifiers (none vs const)}} + X = &Qualifiers::V; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile': different qualifiers (none vs volatile)}} + X = &Qualifiers::R; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() restrict': different qualifiers (none vs restrict)}} + X = &Qualifiers::CV; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile': different qualifiers (none vs const and volatile)}} + X = &Qualifiers::CR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const restrict': different qualifiers (none vs const and restrict)}} + X = &Qualifiers::VR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() volatile restrict': different qualifiers (none vs volatile and restrict)}} + X = &Qualifiers::CVR; // expected-error{{assigning to 'void (test1::Qualifiers::*)()' from incompatible type 'void (test1::Qualifiers::*)() const volatile restrict': different qualifiers (none vs const, volatile, and restrict)}} + } + + struct Dummy { + void N() {}; + }; + + void (Qualifiers::*X)() = &Dummy::N; // expected-error{{cannot initialize a variable of type 'void (test1::Qualifiers::*)()' with an rvalue of type 'void (test1::Dummy::*)()': different classes ('test1::Qualifiers' vs 'test1::Dummy')}} +} diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp index 3c0e448..885bf70 100644 --- a/test/SemaCXX/aggregate-initialization.cpp +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -1,33 +1,33 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -// Verify that we can't initialize non-aggregates with an initializer -// list. +// Verify that using an initializer list for a non-aggregate looks for +// constructors.. // Note that due to a (likely) standard bug, this is technically an aggregate, // but we do not treat it as one. -struct NonAggr1 { - NonAggr1(int) { } +struct NonAggr1 { // expected-note 2 {{candidate constructor}} + NonAggr1(int, int) { } // expected-note {{candidate constructor}} int m; }; struct Base { }; -struct NonAggr2 : public Base { +struct NonAggr2 : public Base { // expected-note 3 {{candidate constructor}} int m; }; -class NonAggr3 { +class NonAggr3 { // expected-note 3 {{candidate constructor}} int m; }; -struct NonAggr4 { +struct NonAggr4 { // expected-note 3 {{candidate constructor}} int m; virtual void f(); }; -NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}} -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}} +NonAggr1 na1 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr1'}} +NonAggr2 na2 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr2'}} +NonAggr3 na3 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr3'}} +NonAggr4 na4 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr4'}} // PR5817 typedef int type[][2]; diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp index 6cff420..484dd33 100644 --- a/test/SemaCXX/alias-template.cpp +++ b/test/SemaCXX/alias-template.cpp @@ -12,12 +12,12 @@ namespace IllegalTypeIds { 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 F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}} 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 = constexpr int; // expected-error {{type name does not allow constexpr specifier}} - template<typename U> using H = void(int n); // ok - template<typename U> using I = void(int n) &&; // ok + template<typename U> using Y = void(int n); // ok + template<typename U> using Z = void(int n) &&; // ok } namespace IllegalSyntax { diff --git a/test/SemaCXX/altivec.cpp b/test/SemaCXX/altivec.cpp index 504eb1b..39421b7 100644 --- a/test/SemaCXX/altivec.cpp +++ b/test/SemaCXX/altivec.cpp @@ -66,3 +66,13 @@ void test2() (++vi)[1]=1; template_f(vi); } + +namespace LValueToRValueConversions { + struct Struct { + float f(); + int n(); + }; + + vector float initFloat = (vector float)(Struct().f); // expected-error {{did you mean to call it}} + vector int initInt = (vector int)(Struct().n); // expected-error {{did you mean to call it}} +} diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp index dfa284a..19a88d7 100644 --- a/test/SemaCXX/anonymous-struct.cpp +++ b/test/SemaCXX/anonymous-struct.cpp @@ -4,8 +4,13 @@ struct S { S(); // expected-note {{because type 'S' has a user-declared constructor}} }; +struct { // expected-error {{anonymous structs and classes must be class members}} +}; + struct E { struct { S x; // expected-error {{anonymous struct member 'x' has a non-trivial constructor}} }; + static struct { + }; }; diff --git a/test/SemaCXX/array-bounds-ptr-arith.cpp b/test/SemaCXX/array-bounds-ptr-arith.cpp index ce1ace6..16e2567 100644 --- a/test/SemaCXX/array-bounds-ptr-arith.cpp +++ b/test/SemaCXX/array-bounds-ptr-arith.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -Warray-bounds-pointer-arithmetic %s +// RUN: %clang_cc1 -verify -Wno-string-plus-int -Warray-bounds-pointer-arithmetic %s void swallow (const char *x) { (void)x; } void test_pointer_arithmetic(int n) { diff --git a/test/SemaCXX/array-bounds-system-header.cpp b/test/SemaCXX/array-bounds-system-header.cpp new file mode 100644 index 0000000..34de5b5 --- /dev/null +++ b/test/SemaCXX/array-bounds-system-header.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -isystem %S/Inputs -verify %s +#include <array-bounds-system-header.h> +void test_system_header_macro() { + BAD_MACRO_1; // no-warning + char a[3]; // expected-note 2 {{declared here}} + BAD_MACRO_2(a, 3); // expected-warning {{array index 3}} + QUESTIONABLE_MACRO(a); + NOP(a[3] = 5); // expected-warning {{array index 3}} +} diff --git a/test/SemaCXX/array-bounds.cpp b/test/SemaCXX/array-bounds.cpp index 555ac33..57a9e3d 100644 --- a/test/SemaCXX/array-bounds.cpp +++ b/test/SemaCXX/array-bounds.cpp @@ -4,16 +4,20 @@ int foo() { int x[2]; // expected-note 4 {{array 'x' declared here}} int y[2]; // expected-note 2 {{array 'y' declared here}} int z[1]; // expected-note {{array 'z' declared here}} + int w[1][1]; // expected-note {{array 'w' declared here}} + int v[1][1][1]; // expected-note {{array 'v' declared here}} int *p = &y[2]; // no-warning (void) sizeof(x[2]); // no-warning - y[2] = 2; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} - z[1] = 'x'; // expected-warning {{array index of '1' indexes past the end of an array (that contains 1 element)}} - return x[2] + // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} - y[-1] + // expected-warning {{array index of '-1' indexes before the beginning of the array}} - x[sizeof(x)] + // expected-warning {{array index of '8' indexes past the end of an array (that contains 2 elements)}} - x[sizeof(x) / sizeof(x[0])] + // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} + y[2] = 2; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + z[1] = 'x'; // expected-warning {{array index 1 is past the end of the array (which contains 1 element)}} + w[0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}} + v[0][0][2] = 0; // expected-warning {{array index 2 is past the end of the array (which contains 1 element)}} + return x[2] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + y[-1] + // expected-warning {{array index -1 is before the beginning of the array}} + x[sizeof(x)] + // expected-warning {{array index 8 is past the end of the array (which contains 2 elements)}} + x[sizeof(x) / sizeof(x[0])] + // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} x[sizeof(x) / sizeof(x[0]) - 1] + // no-warning - x[sizeof(x[2])]; // expected-warning {{array index of '4' indexes past the end of an array (that contains 2 elements)}} + x[sizeof(x[2])]; // expected-warning {{array index 4 is past the end of the array (which contains 2 elements)}} } // This code example tests that -Warray-bounds works with arrays that @@ -27,7 +31,7 @@ void f1(int a[1]) { } void f2(const int (&a)[2]) { // expected-note {{declared here}} - int val = a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + int val = a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} } void test() { @@ -40,33 +44,33 @@ void test() { short a[2]; // expected-note 4 {{declared here}} char c[4]; } u; - u.a[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + u.a[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} u.c[3] = 1; // no warning short *p = &u.a[2]; // no warning - p = &u.a[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} - *(&u.a[2]) = 1; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} - *(&u.a[3]) = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + p = &u.a[3]; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} + *(&u.a[2]) = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} + *(&u.a[3]) = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} *(&u.c[3]) = 1; // no warning const int const_subscript = 3; int array[2]; // expected-note {{declared here}} - array[const_subscript] = 0; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + array[const_subscript] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} int *ptr; ptr[3] = 0; // no warning for pointer references int array2[] = { 0, 1, 2 }; // expected-note 2 {{declared here}} - array2[3] = 0; // expected-warning {{array index of '3' indexes past the end of an array (that contains 3 elements)}} - array2[2+2] = 0; // expected-warning {{array index of '4' indexes past the end of an array (that contains 3 elements)}} + array2[3] = 0; // expected-warning {{array index 3 is past the end of the array (which contains 3 elements)}} + array2[2+2] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}} const char *str1 = "foo"; char c1 = str1[5]; // no warning for pointers const char str2[] = "foo"; // expected-note {{declared here}} - char c2 = str2[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 4 elements)}} + char c2 = str2[5]; // expected-warning {{array index 5 is past the end of the array (which contains 4 elements)}} int (*array_ptr)[2]; - (*array_ptr)[3] = 1; // expected-warning {{array index of '3' indexes past the end of an array (that contains 2 elements)}} + (*array_ptr)[3] = 1; // expected-warning {{array index 3 is past the end of the array (which contains 2 elements)}} } template <int I> struct S { @@ -74,8 +78,8 @@ template <int I> struct S { }; template <int I> void f() { S<3> s; - s.arr[4] = 0; // expected-warning {{array index of '4' indexes past the end of an array (that contains 3 elements)}} - s.arr[I] = 0; // expected-warning {{array index of '5' indexes past the end of an array (that contains 3 elements)}} + s.arr[4] = 0; // expected-warning {{array index 4 is past the end of the array (which contains 3 elements)}} + s.arr[I] = 0; // expected-warning {{array index 5 is past the end of the array (which contains 3 elements)}} } void test_templates() { @@ -88,13 +92,13 @@ void test_templates() { int test_no_warn_macro_unreachable() { int arr[SIZE]; // expected-note {{array 'arr' declared here}} return ARR_IN_MACRO(0, arr, SIZE) + // no-warning - ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index of '10' indexes past the end of an array (that contains 10 elements)}} + ARR_IN_MACRO(1, arr, SIZE); // expected-warning{{array index 10 is past the end of the array (which contains 10 elements)}} } // This exhibited an assertion failure for a 32-bit build of Clang. int test_pr9240() { short array[100]; // expected-note {{array 'array' declared here}} - return array[(unsigned long long) 100]; // expected-warning {{array index of '100' indexes past the end of an array (that contains 100 elements)}} + return array[(unsigned long long) 100]; // expected-warning {{array index 100 is past the end of the array (which contains 100 elements)}} } // PR 9284 - a template parameter can cause an array bounds access to be @@ -112,7 +116,7 @@ void pr9284b() { int arr[3 + (extendArray ? 1 : 0)]; // expected-note {{array 'arr' declared here}} if (!extendArray) - arr[3] = 42; // expected-warning{{array index of '3' indexes past the end of an array (that contains 3 elements)}} + arr[3] = 42; // expected-warning{{array index 3 is past the end of the array (which contains 3 elements)}} } void test_pr9284() { @@ -131,7 +135,7 @@ int test_sizeof_as_condition(int flag) { int arr[2] = { 0, 0 }; // expected-note {{array 'arr' declared here}} if (flag) return sizeof(char) != sizeof(char) ? arr[2] : arr[1]; - return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} + return sizeof(char) == sizeof(char) ? arr[2] : arr[1]; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} } void test_switch() { @@ -143,7 +147,7 @@ void test_switch() { } case 4: { int arr[2]; // expected-note {{array 'arr' declared here}} - arr[2] = 1; // expected-warning {{array index of '2' indexes past the end of an array (that contains 2 elements)}} + arr[2] = 1; // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} break; } default: { @@ -186,10 +190,19 @@ namespace tailpad { int x; char c2[1]; }; - - char bar(struct foo *F) { - return F->c1[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}} - return F->c2[3]; // no warning, foo could have tail padding allocated. + + class baz { + public: + char c1[1]; // expected-note {{declared here}} + int x; + char c2[1]; + }; + + char bar(struct foo *F, baz *B) { + return F->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} + F->c2[3] + // no warning, foo could have tail padding allocated. + B->c1[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} + B->c2[3]; // no warning, baz could have tail padding allocated. } } @@ -199,20 +212,20 @@ namespace metaprogramming { template <int N> struct bar { char c[N]; }; // expected-note {{declared here}} char test(foo *F, bar<1> *B) { - return F->c[3] + // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}} - B->c[3]; // expected-warning {{array index of '3' indexes past the end of an array (that contains 1 element)}} + return F->c[3] + // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} + B->c[3]; // expected-warning {{array index 3 is past the end of the array (which contains 1 element)}} } } void bar(int x) {} int test_more() { int foo[5]; // expected-note 5 {{array 'foo' declared here}} - bar(foo[5]); // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}} - ++foo[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}} - if (foo[6]) // expected-warning {{array index of '6' indexes past the end of an array (that contains 5 elements)}} - return --foo[6]; // expected-warning {{array index of '6' indexes past the end of an array (that contains 5 elements)}} + bar(foo[5]); // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} + ++foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} + if (foo[6]) // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}} + return --foo[6]; // expected-warning {{array index 6 is past the end of the array (which contains 5 elements)}} else - return foo[5]; // expected-warning {{array index of '5' indexes past the end of an array (that contains 5 elements)}} + return foo[5]; // expected-warning {{array index 5 is past the end of the array (which contains 5 elements)}} } void test_pr10771() { @@ -221,7 +234,7 @@ void test_pr10771() { ((char*)foo)[sizeof(foo) - 1] = '\0'; // no-warning *(((char*)foo) + sizeof(foo) - 1) = '\0'; // no-warning - ((char*)foo)[sizeof(foo)] = '\0'; // expected-warning {{array index of '32768' indexes past the end of an array (that contains 32768 elements)}} + ((char*)foo)[sizeof(foo)] = '\0'; // expected-warning {{array index 32768 is past the end of the array (which contains 32768 elements)}} // TODO: This should probably warn, too. *(((char*)foo) + sizeof(foo)) = '\0'; // no-warning @@ -232,6 +245,11 @@ int test_pr11007_aux(const char * restrict, ...); // Test checking with varargs. void test_pr11007() { double a[5]; // expected-note {{array 'a' declared here}} - test_pr11007_aux("foo", a[1000]); // expected-warning {{array index of '1000' indexes past the end of an array}} + test_pr11007_aux("foo", a[1000]); // expected-warning {{array index 1000 is past the end of the array}} } +void test_rdar10916006(void) +{ + int a[128]; // expected-note {{array 'a' declared here}} + a[(unsigned char)'\xA1'] = 1; // expected-warning {{array index 161 is past the end of the array}} +} diff --git a/test/SemaCXX/atomic-type.cxx b/test/SemaCXX/atomic-type.cxx new file mode 100644 index 0000000..18707eb --- /dev/null +++ b/test/SemaCXX/atomic-type.cxx @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -verify %s + +template<typename T> struct atomic { + _Atomic(T) value; +}; + +template<typename T> struct user { + struct inner { char n[sizeof(T)]; }; + atomic<inner> i; +}; + +user<int> u; + +// Test overloading behavior of atomics. +struct A { }; + +int &ovl1(_Atomic(int)); +long &ovl1(_Atomic(long)); +float &ovl1(_Atomic(float)); +double &ovl1(_Atomic(A const *const *)); +short &ovl1(_Atomic(A **)); + +void test_overloading(int i, float f, _Atomic(int) ai, _Atomic(float) af, + long l, _Atomic(long) al, A const *const *acc, + A const ** ac, A **a) { + int& ir1 = ovl1(i); + int& ir2 = ovl1(ai); + long& lr1 = ovl1(l); + long& lr2 = ovl1(al); + float &fr1 = ovl1(f); + float &fr2 = ovl1(af); + double &dr1 = ovl1(acc); + double &dr2 = ovl1(ac); + short &sr1 = ovl1(a); +} diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index de9d7d1..4281895 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -9,6 +9,12 @@ struct align_member { int member alignas(8); }; +template <unsigned A> struct alignas(A) align_class_template {}; + +// FIXME: these should not error +template <typename... T> alignas(T...) struct align_class_temp_pack_type {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}} +template <unsigned... A> alignas(A...) struct align_class_temp_pack_expr {}; // expected-error{{pack expansions in alignment specifiers are not supported yet}} + typedef char align_typedef alignas(8); template<typename T> using align_alias_template = align_typedef; @@ -18,4 +24,9 @@ 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_class_template<8>) == 8, "template's alignment is wrong"); +static_assert(alignof(align_class_template<16>) == 16, "template's alignment is wrong"); +// FIXME: enable these tests +// static_assert(alignof(align_class_temp_pack_type<short, int, long>) == alignof(long), "template's alignment is wrong"); +// static_assert(alignof(align_class_temp_pack_expr<8, 16, 32>) == 32, "template's alignment is wrong"); static_assert(alignof(align_alias_template<int>) == 8, "alias template's alignment is wrong"); diff --git a/test/SemaCXX/attr-declspec-ignored.cpp b/test/SemaCXX/attr-declspec-ignored.cpp new file mode 100644 index 0000000..0503750 --- /dev/null +++ b/test/SemaCXX/attr-declspec-ignored.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +namespace test1 { + __attribute__((visibility("hidden"))) __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "class" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B; // expected-warning{{attribute 'visibility' is ignored, place it after "struct" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "struct" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) union C; // expected-warning{{attribute 'visibility' is ignored, place it after "union" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "union" to apply attribute to type declaration}} + __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum" to apply attribute to type declaration}} \ + // expected-warning{{attribute 'aligned' is ignored, place it after "enum" to apply attribute to type declaration}} +} + +namespace test2 { + __attribute__((visibility("hidden"))) __attribute__((aligned)) class A {} a; + __attribute__((visibility("hidden"))) __attribute__((aligned)) struct B {} b; + __attribute__((visibility("hidden"))) __attribute__((aligned)) union C {} c; + __attribute__((visibility("hidden"))) __attribute__((aligned)) enum D {D} d; +} diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index 945aff3..46568aa 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -198,7 +198,7 @@ namespace test6 { }; void testA() { A x; // expected-warning {{'A' is deprecated}} - x = a0; // expected-warning {{'A' is deprecated}} + x = a0; // expected-warning {{'a0' is deprecated}} } enum B { @@ -218,7 +218,7 @@ namespace test6 { }; void testC() { C<int>::Enum x; // expected-warning {{'Enum' is deprecated}} - x = C<int>::c0; // expected-warning {{'Enum' is deprecated}} + x = C<int>::c0; // expected-warning {{'c0' is deprecated}} } template <class T> struct D { diff --git a/test/SemaCXX/attr-sentinel.cpp b/test/SemaCXX/attr-sentinel.cpp index 56c8f88..92c6e21 100644 --- a/test/SemaCXX/attr-sentinel.cpp +++ b/test/SemaCXX/attr-sentinel.cpp @@ -1,6 +1,23 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s + void f(int, ...) __attribute__((sentinel)); void g() { f(1, 2, __null); } + +typedef __typeof__(sizeof(int)) size_t; + +struct S { + S(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} + void a(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} + void* operator new(size_t,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} + void operator()(int,...) __attribute__((sentinel)); // expected-note {{marked sentinel}} +}; + +void class_test() { + S s(1,2,3); // expected-warning {{missing sentinel in function call}} + S* s2 = new (1,2,3) S(1, __null); // expected-warning {{missing sentinel in function call}} + s2->a(1,2,3); // expected-warning {{missing sentinel in function call}} + s(1,2,3); // expected-warning {{missing sentinel in function call}} +} diff --git a/test/SemaCXX/auto-cxx98.cpp b/test/SemaCXX/auto-cxx98.cpp index 6c401ba..1e28d06 100644 --- a/test/SemaCXX/auto-cxx98.cpp +++ b/test/SemaCXX/auto-cxx98.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wc++11-compat void f() { auto int a; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} int auto b; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} diff --git a/test/SemaCXX/blocks-1.cpp b/test/SemaCXX/blocks-1.cpp index 29de1e6..1b15094 100644 --- a/test/SemaCXX/blocks-1.cpp +++ b/test/SemaCXX/blocks-1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks +// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++11 extern "C" int exit(int); @@ -43,3 +43,16 @@ namespace rdar8134521 { P = (int(^)(int))((void*)1); } } + +namespace rdar11055105 { + struct A { + void foo(); + }; + + template <class T> void foo(T &x) noexcept(noexcept(x.foo())); + + void (^block)() = ^{ + A a; + foo(a); + }; +} diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp index 3f1d6a8..7773c08 100644 --- a/test/SemaCXX/c99-variable-length-array.cpp +++ b/test/SemaCXX/c99-variable-length-array.cpp @@ -14,8 +14,8 @@ struct POD { // We allow VLAs of POD types, only. void vla(int N) { - int array1[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} - POD array2[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + int array1[N]; // expected-warning{{variable length arrays are a C99 feature}} + POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}} NonPOD array3[N]; // expected-error{{variable length array of non-POD element type 'NonPOD'}} NonPOD2 array4[N][3]; // expected-error{{variable length array of non-POD element type 'NonPOD2'}} } @@ -23,7 +23,7 @@ void vla(int N) { /// Warn about VLAs in templates. template<typename T> void vla_in_template(int N, T t) { - int array1[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + int array1[N]; // expected-warning{{variable length arrays are a C99 feature}} } struct HasConstantValue { @@ -36,7 +36,7 @@ struct HasNonConstantValue { template<typename T> void vla_in_template(T t) { - int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature}} } template void vla_in_template<HasConstantValue>(HasConstantValue); @@ -47,14 +47,14 @@ template<typename T> struct X0 { }; // Cannot use any variably-modified type with a template parameter or // argument. void inst_with_vla(int N) { - int array[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + int array[N]; // expected-warning{{variable length arrays are a C99 feature}} X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int [N]') cannot be used as a template argument}} } template<typename T> struct X1 { template<int (&Array)[T::value]> // expected-error{{non-type template parameter of variably modified type 'int (&)[HasNonConstantValue::value]'}} \ - // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + // expected-warning{{variable length arrays are a C99 feature}} struct Inner { }; @@ -68,16 +68,17 @@ template<typename T, unsigned N> void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: failed template argument deduction}} void test_accept_array(int N) { - int array[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + int array[N]; // expected-warning{{variable length arrays are a C99 feature}} accept_array(array); // expected-error{{no matching function for call to 'accept_array'}} } // Variably-modified types cannot be used in local classes. -void local_classes(int N) { +void local_classes(int N) { // expected-note {{declared here}} struct X { int size; int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \ - // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + // expected-error{{reference to local variable 'N' declared in enclosing function 'local_classes'}} \ + // expected-warning{{variable length arrays are a C99 feature}} }; } @@ -87,7 +88,7 @@ namespace PR7206 { float left; float right; }; - struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature}} } } @@ -95,7 +96,7 @@ namespace rdar8020206 { template<typename T> void f(int i) { const unsigned value = i; - int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature, accepted as an extension}} + int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature}} } template void f<int>(int); // expected-note{{instantiation of}} @@ -109,7 +110,7 @@ namespace rdar8021385 { typedef typename T::my_int my_int; void f0() { int M = 4; - my_int a[M]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + my_int a[M]; // expected-warning{{variable length arrays are a C99 feature}} } }; B<A> a; @@ -117,7 +118,7 @@ namespace rdar8021385 { namespace PR8209 { void f(int n) { - typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}} + typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature}} (void)new vla_type; // expected-error{{variably}} } } @@ -130,3 +131,11 @@ static const int k_cVal3 = (int)(1000*0.2f); char rgch[k_cVal3] = {0}; } } + +namespace PR11744 { + template<typename T> int f(int n) { + T arr[3][n]; // expected-warning 3 {{variable length arrays are a C99 feature}} + return 3; + } + int test = f<int>(0); // expected-note {{instantiation of}} +} diff --git a/test/SemaCXX/c99.cpp b/test/SemaCXX/c99.cpp index cda069c..13918dc 100644 --- a/test/SemaCXX/c99.cpp +++ b/test/SemaCXX/c99.cpp @@ -4,6 +4,6 @@ void f1(int i[static 5]) { // expected-error{{C99}} struct Point { int x; int y; }; -Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature, accepted in C++ as an extension}} - y: 25 }; // expected-warning{{designated initializers are a C99 feature, accepted in C++ as an extension}} \ +Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature}} + y: 25 }; // expected-warning{{designated initializers are a C99 feature}} \ // expected-warning{{use of GNU old-style field designator extension}} diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp index ca9f045..e84e57b 100644 --- a/test/SemaCXX/class-base-member-init.cpp +++ b/test/SemaCXX/class-base-member-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s class S { public: @@ -69,8 +69,24 @@ namespace test4 { }; A(char _) : a(0), b(0) {} - A(short _) : a(0), c(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}} - A(int _) : d(0), e(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}} - A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of anonymous union}} expected-note {{previous initialization is here}} + A(short _) : a(0), c(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}} + A(int _) : d(0), e(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}} + A(long _) : a(0), d(0) {} // expected-error {{initializing multiple members of union}} expected-note {{previous initialization is here}} + }; +} + +namespace test5 { + struct Base { + Base(int); + }; + struct A : Base { + A() : decltype(Base(1))(3) { + } + A(int) : Base(3), // expected-note {{previous initialization is here}} + decltype(Base(1))(2), // expected-error {{multiple initializations given for base 'decltype(test5::Base(1))' (aka 'test5::Base')}} + decltype(int())() { // expected-error {{constructor initializer 'decltype(int())' (aka 'int') does not name a class}} + } + A(float) : decltype(A())(3) { + } }; } diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp index 160f365..4dffc8d 100644 --- a/test/SemaCXX/class.cpp +++ b/test/SemaCXX/class.cpp @@ -1,22 +1,24 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s class C { public: - auto int errx; // expected-error {{error: storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}} - 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}} + auto int errx; // expected-error {{storage class specified for a member declaration}} expected-warning {{'auto' storage class specifier is redundant}} + register int erry; // expected-error {{storage class specified for a member declaration}} + extern int errz; // expected-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}} + this->x = 0; // expected-error {{invalid use of 'this' outside of a non-static member function}} + x = 0; // expected-error {{invalid use of member 'x' in static member function}} } class NestedC { public: NestedC(int); - void m() { + void f() { sx = 0; - x = 0; // expected-error {{invalid use of nonstatic data member 'x'}} + x = 0; // expected-error {{use of non-static data member 'x' of 'C' from nested type 'NestedC'}} + sm(); + m(); // expected-error {{call to non-static member function 'm' of 'C' from nested type 'NestedC'}} } }; @@ -34,10 +36,10 @@ public: enum E1 { en1, en2 }; - int i = 0; // expected-warning {{in-class initialization of non-static data member accepted as a C++11 extension}} + int i = 0; // expected-warning {{in-class initialization of non-static data member is a C++11 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}} + static const int nci = vs; // expected-error {{in-class initializer for static data member is not a constant expression}} static const int vi = 0; static const volatile int cvi = 0; // ok, illegal in C++11 static const E evi = 0; @@ -46,7 +48,7 @@ public: sx = 0; this->x = 0; y = 0; - this = 0; // expected-error {{error: expression is not assignable}} + this = 0; // expected-error {{expression is not assignable}} } int f1(int p) { @@ -57,7 +59,7 @@ public: 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 static int vsif(); // expected-error {{'virtual' can only appear on non-static member functions}} virtual int vif(); private: @@ -65,9 +67,9 @@ private: 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}} + mutable int &mir; // expected-error {{'mutable' cannot be applied to references}} + mutable void mfn(); // expected-error {{'mutable' cannot be applied to functions}} + mutable const int mci; // expected-error {{'mutable' and 'const' cannot be mixed}} static const int number = 50; static int arr[number]; @@ -98,11 +100,11 @@ void f() } // 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 int gi; // expected-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}} + mutable int ml; // expected-error {{'mutable' can only be applied to member variables}} // PR3020: This used to crash due to double ownership of C4. struct C4; @@ -129,10 +131,10 @@ namespace pr6629 { bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} \ // BOGUS expected-error {{expected '{' after base class list}} \ // BOGUS expected-error {{expected ';' after struct}} \ - // BOGUS expected-error {{expected unqualified-id}} \ + // BOGUS expected-error {{expected unqualified-id}} { }; - template<> struct foo<unknown,unknown> { // why isn't there an error here? + template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}} template <typename U1, typename U2> struct bar { typedef bar type; static const int value = 0; @@ -174,7 +176,7 @@ namespace rdar8367341 { struct A { static const float x = 5.0f; // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} - static const float y = foo(); // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} expected-error {{in-class initializer is not a constant expression}} + static const float y = foo(); // expected-warning {{in-class initializer for static data member of type 'const float' is a GNU extension}} expected-error {{in-class initializer for static data member is not a constant expression}} }; } @@ -186,7 +188,7 @@ struct S { }; void f() { - S::c; // expected-error {{invalid use of nonstatic data member}} + S::c; // expected-error {{invalid use of non-static data member}} } } diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp index 2c057ac..719a850 100644 --- a/test/SemaCXX/complex-overload.cpp +++ b/test/SemaCXX/complex-overload.cpp @@ -32,7 +32,7 @@ int *promote_or_convert(long double _Complex); // expected-note{{candidate funct 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:}} + int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous}} } char *promote_or_convert2(float); diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index 3441bae..993f8e1 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -7,7 +7,7 @@ void test() { typedef int arr[10]; while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}} - while (int f()=0) ; // expected-error {{a function type is not allowed here}} + while (int f()=0) ; // expected-warning {{interpreted as a function declaration}} expected-note {{initializer}} 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'}} @@ -20,7 +20,8 @@ void test() { while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}} while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}} switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \ - // expected-warning{{enumeration value 'E' not handled in switch}} + // expected-warning{{enumeration value 'E' not handled in switch}} expected-warning {{switch statement has empty body}} \ + // expected-note{{put the semicolon on a separate line}} if (int x=0) { // expected-note 2 {{previous definition is here}} int x; // expected-error {{redefinition of 'x'}} @@ -49,6 +50,11 @@ void test3() { if ("help") (void) 0; - if (test3) + if (test3) // expected-warning {{address of function 'test3' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} (void) 0; } + +void test4(bool (&x)(void)) { + while (x); +} diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 5648d02..4aee913 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -96,8 +96,8 @@ void test() (void)(i1 ? BadDerived() : BadBase()); // b2.1 (hierarchy stuff) - const Base constret(); - const Derived constder(); + extern const Base constret(); + extern const Derived constder(); // should use const overload A a1((i1 ? constret() : Base()).trick()); A a2((i1 ? Base() : constret()).trick()); diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp new file mode 100644 index 0000000..41d214a --- /dev/null +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -0,0 +1,1246 @@ +// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -verify -std=c++11 -pedantic %s -Wno-comment + +namespace StaticAssertFoldTest { + +int x; +static_assert(++x, "test"); // expected-error {{not an integral constant expression}} +static_assert(false, "test"); // expected-error {{test}} + +} + +typedef decltype(sizeof(char)) size_t; + +template<typename T> constexpr T id(const T &t) { return t; } +template<typename T> constexpr T min(const T &a, const T &b) { + return a < b ? a : b; +} +template<typename T> constexpr T max(const T &a, const T &b) { + return a < b ? b : a; +} +template<typename T, size_t N> constexpr T *begin(T (&xs)[N]) { return xs; } +template<typename T, size_t N> constexpr T *end(T (&xs)[N]) { return xs + N; } + +struct MemberZero { + constexpr int zero() { return 0; } +}; + +namespace DerivedToVBaseCast { + + struct U { int n; }; + struct V : U { int n; }; + struct A : virtual V { int n; }; + struct Aa { int n; }; + struct B : virtual A, Aa {}; + struct C : virtual A, Aa {}; + struct D : B, C {}; + + D d; + constexpr B *p = &d; + constexpr C *q = &d; + + static_assert((void*)p != (void*)q, ""); + static_assert((A*)p == (A*)q, ""); + static_assert((Aa*)p != (Aa*)q, ""); + + constexpr B &pp = d; + constexpr C &qq = d; + static_assert((void*)&pp != (void*)&qq, ""); + static_assert(&(A&)pp == &(A&)qq, ""); + static_assert(&(Aa&)pp != &(Aa&)qq, ""); + + constexpr V *v = p; + constexpr V *w = q; + constexpr V *x = (A*)p; + static_assert(v == w, ""); + static_assert(v == x, ""); + + static_assert((U*)&d == p, ""); + static_assert((U*)&d == q, ""); + static_assert((U*)&d == v, ""); + static_assert((U*)&d == w, ""); + static_assert((U*)&d == x, ""); + + struct X {}; + struct Y1 : virtual X {}; + struct Y2 : X {}; + struct Z : Y1, Y2 {}; + Z z; + static_assert((X*)(Y1*)&z != (X*)(Y2*)&z, ""); +} + +namespace ConstCast { + +constexpr int n1 = 0; +constexpr int n2 = const_cast<int&>(n1); +constexpr int *n3 = const_cast<int*>(&n1); +constexpr int n4 = *const_cast<int*>(&n1); +constexpr const int * const *n5 = const_cast<const int* const*>(&n3); +constexpr int **n6 = const_cast<int**>(&n3); +constexpr int n7 = **n5; +constexpr int n8 = **n6; + +} + +namespace TemplateArgumentConversion { + template<int n> struct IntParam {}; + + using IntParam0 = IntParam<0>; + using IntParam0 = IntParam<id(0)>; + using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} +} + +namespace CaseStatements { + void f(int n) { + switch (n) { + case MemberZero().zero: // expected-error {{did you mean to call it with no arguments?}} expected-note {{previous}} + case id(0): // expected-error {{duplicate case value '0'}} + return; + } + } +} + +extern int &Recurse1; +int &Recurse2 = Recurse1; // expected-note {{declared here}} +int &Recurse1 = Recurse2; +constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'Recurse2' is not a constant expression}} + +extern const int RecurseA; +const int RecurseB = RecurseA; // expected-note {{declared here}} +const int RecurseA = 10; +constexpr int RecurseC = RecurseB; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'RecurseB' is not a constant expression}} + +namespace MemberEnum { + struct WithMemberEnum { + enum E { A = 42 }; + } wme; + + static_assert(wme.A == 42, ""); +} + +namespace DefaultArguments { + +const int z = int(); +constexpr int Sum(int a = 0, const int &b = 0, const int *c = &z, char d = 0) { + return a + b + *c + d; +} +const int four = 4; +constexpr int eight = 8; +constexpr const int twentyseven = 27; +static_assert(Sum() == 0, ""); +static_assert(Sum(1) == 1, ""); +static_assert(Sum(1, four) == 5, ""); +static_assert(Sum(1, eight, &twentyseven) == 36, ""); +static_assert(Sum(1, 2, &four, eight) == 15, ""); + +} + +namespace Ellipsis { + +// Note, values passed through an ellipsis can't actually be used. +constexpr int F(int a, ...) { return a; } +static_assert(F(0) == 0, ""); +static_assert(F(1, 0) == 1, ""); +static_assert(F(2, "test") == 2, ""); +static_assert(F(3, &F) == 3, ""); +int k = 0; // expected-note {{here}} +static_assert(F(4, k) == 3, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'k'}} + +} + +namespace Recursion { + constexpr int fib(int n) { return n > 1 ? fib(n-1) + fib(n-2) : n; } + static_assert(fib(11) == 89, ""); + + constexpr int gcd_inner(int a, int b) { + return b == 0 ? a : gcd_inner(b, a % b); + } + constexpr int gcd(int a, int b) { + return gcd_inner(max(a, b), min(a, b)); + } + + static_assert(gcd(1749237, 5628959) == 7, ""); +} + +namespace FunctionCast { + // When folding, we allow functions to be cast to different types. Such + // cast functions cannot be called, even if they're constexpr. + constexpr int f() { return 1; } + typedef double (*DoubleFn)(); + typedef int (*IntFn)(); + int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}} expected-warning{{C99 feature}} + int b[(int)IntFn(f)()]; // ok +} + +namespace StaticMemberFunction { + struct S { + static constexpr int k = 42; + static constexpr int f(int n) { return n * k + 2; } + } s; + + constexpr int n = s.f(19); + static_assert(S::f(19) == 800, ""); + static_assert(s.f(19) == 800, ""); + static_assert(n == 800, ""); + + constexpr int (*sf1)(int) = &S::f; + constexpr int (*sf2)(int) = &s.f; + constexpr const int *sk = &s.k; +} + +namespace ParameterScopes { + + const int k = 42; + constexpr const int &ObscureTheTruth(const int &a) { return a; } + constexpr const int &MaybeReturnJunk(bool b, const int a) { // expected-note 2{{declared here}} + return ObscureTheTruth(b ? a : k); + } + static_assert(MaybeReturnJunk(false, 0) == 42, ""); // ok + constexpr int a = MaybeReturnJunk(true, 0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}} + + constexpr const int MaybeReturnNonstaticRef(bool b, const int a) { + return ObscureTheTruth(b ? a : k); + } + static_assert(MaybeReturnNonstaticRef(false, 0) == 42, ""); // ok + constexpr int b = MaybeReturnNonstaticRef(true, 0); // ok + + constexpr int InternalReturnJunk(int n) { + return MaybeReturnJunk(true, n); // expected-note {{read of variable whose lifetime has ended}} + } + constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'InternalReturnJunk(0)'}} + + constexpr int LToR(int &n) { return n; } + constexpr int GrabCallersArgument(bool which, int a, int b) { + return LToR(which ? b : a); + } + static_assert(GrabCallersArgument(false, 1, 2) == 1, ""); + static_assert(GrabCallersArgument(true, 4, 8) == 8, ""); + +} + +namespace Pointers { + + constexpr int f(int n, const int *a, const int *b, const int *c) { + return n == 0 ? 0 : *a + f(n-1, b, c, a); + } + + const int x = 1, y = 10, z = 100; + static_assert(f(23, &x, &y, &z) == 788, ""); + + constexpr int g(int n, int a, int b, int c) { + return f(n, &a, &b, &c); + } + static_assert(g(23, x, y, z) == 788, ""); + +} + +namespace FunctionPointers { + + constexpr int Double(int n) { return 2 * n; } + constexpr int Triple(int n) { return 3 * n; } + constexpr int Twice(int (*F)(int), int n) { return F(F(n)); } + constexpr int Quadruple(int n) { return Twice(Double, n); } + constexpr auto Select(int n) -> int (*)(int) { + return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0; + } + constexpr int Apply(int (*F)(int), int n) { return F(n); } // expected-note {{subexpression}} + + static_assert(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, ""); + + constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Apply(0, 0)'}} + +} + +namespace PointerComparison { + +int x, y; +static_assert(&x == &y, "false"); // expected-error {{false}} +static_assert(&x != &y, ""); +constexpr bool g1 = &x == &y; +constexpr bool g2 = &x != &y; +constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool g6 = &x > &y; // expected-error {{must be initialized by a constant expression}} + +struct S { int x, y; } s; +static_assert(&s.x == &s.y, "false"); // expected-error {{false}} +static_assert(&s.x != &s.y, ""); +static_assert(&s.x <= &s.y, ""); +static_assert(&s.x >= &s.y, "false"); // expected-error {{false}} +static_assert(&s.x < &s.y, ""); +static_assert(&s.x > &s.y, "false"); // expected-error {{false}} + +static_assert(0 == &y, "false"); // expected-error {{false}} +static_assert(0 != &y, ""); +constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}} +constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}} + +static_assert(&x == 0, "false"); // expected-error {{false}} +static_assert(&x != 0, ""); +constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}} +constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}} + +static_assert(&x == &x, ""); +static_assert(&x != &x, "false"); // expected-error {{false}} +static_assert(&x <= &x, ""); +static_assert(&x >= &x, ""); +static_assert(&x < &x, "false"); // expected-error {{false}} +static_assert(&x > &x, "false"); // expected-error {{false}} + +constexpr S* sptr = &s; +constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr); // expected-error {{constant expression}} expected-note {{dynamic_cast}} + +struct U {}; +struct Str { + int a : dynamic_cast<S*>(sptr) == dynamic_cast<S*>(sptr); // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{dynamic_cast is not allowed in a constant expression}} + int b : reinterpret_cast<S*>(sptr) == reinterpret_cast<S*>(sptr); // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{reinterpret_cast is not allowed in a constant expression}} + int c : (S*)(long)(sptr) == (S*)(long)(sptr); // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + int d : (S*)(42) == (S*)(42); // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + int e : (Str*)(sptr) == (Str*)(sptr); // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + int f : &(U&)(*sptr) == &(U&)(*sptr); // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + int g : (S*)(void*)(sptr) == sptr; // \ + expected-warning {{not an integral constant expression}} \ + expected-note {{cast from 'void *' is not allowed in a constant expression}} +}; + +extern char externalvar[]; +constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; // expected-error {{must be initialized by a constant expression}} +constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}} expected-warning {{unspecified}} +static_assert(0 != "foo", ""); + +} + +namespace MaterializeTemporary { + +constexpr int f(const int &r) { return r; } +constexpr int n = f(1); + +constexpr bool same(const int &a, const int &b) { return &a == &b; } +constexpr bool sameTemporary(const int &n) { return same(n, n); } + +static_assert(n, ""); +static_assert(!same(4, 4), ""); +static_assert(same(n, n), ""); +static_assert(sameTemporary(9), ""); + +} + +constexpr int strcmp_ce(const char *p, const char *q) { + return (!*p || *p != *q) ? *p - *q : strcmp_ce(p+1, q+1); +} + +namespace StringLiteral { + +template<typename Char> +constexpr int MangleChars(const Char *p) { + return *p + 3 * (*p ? MangleChars(p+1) : 0); +} + +static_assert(MangleChars("constexpr!") == 1768383, ""); +static_assert(MangleChars(u8"constexpr!") == 1768383, ""); +static_assert(MangleChars(L"constexpr!") == 1768383, ""); +static_assert(MangleChars(u"constexpr!") == 1768383, ""); +static_assert(MangleChars(U"constexpr!") == 1768383, ""); + +constexpr char c0 = "nought index"[0]; +constexpr char c1 = "nice index"[10]; +constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}} expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}} expected-note {{cannot refer to element -1 of array of 15 elements}} +constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast which performs the conversions of a reinterpret_cast}} + +constexpr const char *p = "test" + 2; +static_assert(*p == 's', ""); + +constexpr const char *max_iter(const char *a, const char *b) { + return *a < *b ? b : a; +} +constexpr const char *max_element(const char *a, const char *b) { + return (a+1 >= b) ? a : max_iter(a, max_element(a+1, b)); +} + +constexpr char str[] = "the quick brown fox jumped over the lazy dog"; +constexpr const char *max = max_element(begin(str), end(str)); +static_assert(*max == 'z', ""); +static_assert(max == str + 38, ""); + +static_assert(strcmp_ce("hello world", "hello world") == 0, ""); +static_assert(strcmp_ce("hello world", "hello clang") > 0, ""); +static_assert(strcmp_ce("constexpr", "test") < 0, ""); +static_assert(strcmp_ce("", " ") < 0, ""); + +struct S { + int n : "foo"[4]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} +}; + +struct T { + char c[6]; + constexpr T() : c{"foo"} {} +}; +constexpr T t; + +static_assert(t.c[0] == 'f', ""); +static_assert(t.c[1] == 'o', ""); +static_assert(t.c[2] == 'o', ""); +static_assert(t.c[3] == 0, ""); +static_assert(t.c[4] == 0, ""); +static_assert(t.c[5] == 0, ""); +static_assert(t.c[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}} + +struct U { + wchar_t chars[6]; + int n; +} constexpr u = { { L"test" }, 0 }; +static_assert(u.chars[2] == L's', ""); + +struct V { + char c[4]; + constexpr V() : c("hi!") {} +}; +static_assert(V().c[1] == "i"[0], ""); + +} + +namespace Array { + +template<typename Iter> +constexpr auto Sum(Iter begin, Iter end) -> decltype(+*begin) { + return begin == end ? 0 : *begin + Sum(begin+1, end); +} + +constexpr int xs[] = { 1, 2, 3, 4, 5 }; +constexpr int ys[] = { 5, 4, 3, 2, 1 }; +constexpr int sum_xs = Sum(begin(xs), end(xs)); +static_assert(sum_xs == 15, ""); + +constexpr int ZipFoldR(int (*F)(int x, int y, int c), int n, + const int *xs, const int *ys, int c) { + return n ? F( + *xs, // expected-note {{read of dereferenced one-past-the-end pointer}} + *ys, + ZipFoldR(F, n-1, xs+1, ys+1, c)) // \ + expected-note {{in call to 'ZipFoldR(&SubMul, 2, &xs[4], &ys[4], 1)'}} \ + expected-note {{in call to 'ZipFoldR(&SubMul, 1, &xs[5], &ys[5], 1)'}} + : c; +} +constexpr int MulAdd(int x, int y, int c) { return x * y + c; } +constexpr int InnerProduct = ZipFoldR(MulAdd, 5, xs, ys, 0); +static_assert(InnerProduct == 35, ""); + +constexpr int SubMul(int x, int y, int c) { return (x - y) * c; } +constexpr int DiffProd = ZipFoldR(SubMul, 2, xs+3, ys+3, 1); +static_assert(DiffProd == 8, ""); +static_assert(ZipFoldR(SubMul, 3, xs+3, ys+3, 1), ""); // \ + expected-error {{constant expression}} \ + expected-note {{in call to 'ZipFoldR(&SubMul, 3, &xs[3], &ys[3], 1)'}} + +constexpr const int *p = xs + 3; +constexpr int xs4 = p[1]; // ok +constexpr int xs5 = p[2]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr int xs6 = p[3]; // expected-error {{constant expression}} expected-note {{cannot refer to element 6}} +constexpr int xs0 = p[-3]; // ok +constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} + +constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; +static_assert(zs[0][0][0][0] == 1, ""); +static_assert(zs[1][1][1][1] == 16, ""); +static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +static_assert((&zs[0][0][0][2])[-1] == 2, ""); +static_assert(**(**(zs + 1) + 1) == 11, ""); +static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of array of 2 elements in a constant expression}} +static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2) == 11, ""); +constexpr int err_zs_1_2_0_0 = zs[1][2][0][0]; // expected-error {{constant expression}} expected-note {{cannot access array element of pointer past the end}} + +constexpr int fail(const int &p) { + return (&p)[64]; // expected-note {{cannot refer to element 64 of array of 2 elements}} +} +static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // \ +expected-error {{static_assert expression is not an integral constant expression}} \ +expected-note {{in call to 'fail(zs[1][0][1][0])'}} + +constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; // expected-warning {{C99 feature}} +constexpr int SumNonzero(const int *p) { + return *p + (*p ? SumNonzero(p+1) : 0); +} +constexpr int CountZero(const int *p, const int *q) { + return p == q ? 0 : (*p == 0) + CountZero(p+1, q); +} +static_assert(SumNonzero(arr) == 6, ""); +static_assert(CountZero(arr, arr + 40) == 36, ""); + +struct ArrayElem { + constexpr ArrayElem() : n(0) {} + int n; + constexpr int f() { return n; } +}; +struct ArrayRVal { + constexpr ArrayRVal() {} + ArrayElem elems[10]; +}; +static_assert(ArrayRVal().elems[3].f() == 0, ""); + +} + +namespace DependentValues { + +struct I { int n; typedef I V[10]; }; +I::V x, y; +template<bool B> struct S { + int k; + void f() { + I::V &cells = B ? x : y; + I &i = cells[k]; + switch (i.n) {} + } +}; + +} + +namespace Class { + +struct A { constexpr A(int a, int b) : k(a + b) {} int k; }; +constexpr int fn(const A &a) { return a.k; } +static_assert(fn(A(4,5)) == 9, ""); + +struct B { int n; int m; } constexpr b = { 0, b.n }; // expected-warning {{uninitialized}} +struct C { + constexpr C(C *this_) : m(42), n(this_->m) {} // ok + int m, n; +}; +struct D { + C c; + constexpr D() : c(&c) {} +}; +static_assert(D().c.n == 42, ""); + +struct E { + constexpr E() : p(&p) {} + void *p; +}; +constexpr const E &e1 = E(); // expected-error {{constant expression}} expected-note {{reference to temporary is not a constant expression}} expected-note {{temporary created here}} +// This is a constant expression if we elide the copy constructor call, and +// is not a constant expression if we don't! But we do, so it is. +constexpr E e2 = E(); +static_assert(e2.p == &e2.p, ""); +constexpr E e3; +static_assert(e3.p == &e3.p, ""); + +extern const class F f; +struct F { + constexpr F() : p(&f.p) {} + const void *p; +}; +constexpr F f; + +struct G { + struct T { + constexpr T(T *p) : u1(), u2(p) {} + union U1 { + constexpr U1() {} + int a, b = 42; + } u1; + union U2 { + constexpr U2(T *p) : c(p->u1.b) {} + int c, d; + } u2; + } t; + constexpr G() : t(&t) {} +} constexpr g; + +static_assert(g.t.u1.a == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}} +static_assert(g.t.u1.b == 42, ""); +static_assert(g.t.u2.c == 42, ""); +static_assert(g.t.u2.d == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'd' of union with active member 'c'}} + +struct S { + int a, b; + const S *p; + double d; + const char *q; + + constexpr S(int n, const S *p) : a(5), b(n), p(p), d(n), q("hello") {} +}; + +S global(43, &global); + +static_assert(S(15, &global).b == 15, ""); + +constexpr bool CheckS(const S &s) { + return s.a == 5 && s.b == 27 && s.p == &global && s.d == 27. && s.q[3] == 'l'; +} +static_assert(CheckS(S(27, &global)), ""); + +struct Arr { + char arr[3]; + constexpr Arr() : arr{'x', 'y', 'z'} {} +}; +constexpr int hash(Arr &&a) { + return a.arr[0] + a.arr[1] * 0x100 + a.arr[2] * 0x10000; +} +constexpr int k = hash(Arr()); +static_assert(k == 0x007a7978, ""); + + +struct AggregateInit { + const char &c; + int n; + double d; + int arr[5]; + void *p; +}; + +constexpr AggregateInit agg1 = { "hello"[0] }; + +static_assert(strcmp_ce(&agg1.c, "hello") == 0, ""); +static_assert(agg1.n == 0, ""); +static_assert(agg1.d == 0.0, ""); +static_assert(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} +static_assert(agg1.arr[0] == 0, ""); +static_assert(agg1.arr[4] == 0, ""); +static_assert(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end}} +static_assert(agg1.p == nullptr, ""); + +namespace SimpleDerivedClass { + +struct B { + constexpr B(int n) : a(n) {} + int a; +}; +struct D : B { + constexpr D(int n) : B(n) {} +}; +constexpr D d(3); +static_assert(d.a == 3, ""); + +} + +struct Bottom { constexpr Bottom() {} }; +struct Base : Bottom { + constexpr Base(int a = 42, const char *b = "test") : a(a), b(b) {} + int a; + const char *b; +}; +struct Base2 : Bottom { + constexpr Base2(const int &r) : r(r) {} + int q = 123; + const int &r; +}; +struct Derived : Base, Base2 { + constexpr Derived() : Base(76), Base2(a) {} + int c = r + b[1]; +}; + +constexpr bool operator==(const Base &a, const Base &b) { + return a.a == b.a && strcmp_ce(a.b, b.b) == 0; +} + +constexpr Base base; +constexpr Base base2(76); +constexpr Derived derived; +static_assert(derived.a == 76, ""); +static_assert(derived.b[2] == 's', ""); +static_assert(derived.c == 76 + 'e', ""); +static_assert(derived.q == 123, ""); +static_assert(derived.r == 76, ""); +static_assert(&derived.r == &derived.a, ""); + +static_assert(!(derived == base), ""); +static_assert(derived == base2, ""); + +constexpr Bottom &bot1 = (Base&)derived; +constexpr Bottom &bot2 = (Base2&)derived; +static_assert(&bot1 != &bot2, ""); + +constexpr Bottom *pb1 = (Base*)&derived; +constexpr Bottom *pb2 = (Base2*)&derived; +static_assert(&pb1 != &pb2, ""); +static_assert(pb1 == &bot1, ""); +static_assert(pb2 == &bot2, ""); + +constexpr Base2 &fail = (Base2&)bot1; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base2'}} +constexpr Base &fail2 = (Base&)*pb2; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base'}} +constexpr Base2 &ok2 = (Base2&)bot2; +static_assert(&ok2 == &derived, ""); + +constexpr Base2 *pfail = (Base2*)pb1; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base2'}} +constexpr Base *pfail2 = (Base*)&bot2; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'const Class::Derived' to type 'Class::Base'}} +constexpr Base2 *pok2 = (Base2*)pb2; +static_assert(pok2 == &derived, ""); +static_assert(&ok2 == pok2, ""); +static_assert((Base2*)(Derived*)(Base*)pb1 == pok2, ""); +static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, ""); + +constexpr Base *nullB = 42 - 6 * 7; +static_assert((Bottom*)nullB == 0, ""); +static_assert((Derived*)nullB == 0, ""); +static_assert((void*)(Bottom*)nullB == (void*)(Derived*)nullB, ""); + +namespace ConversionOperators { + +struct T { + constexpr T(int n) : k(5*n - 3) {} + constexpr operator int() { return k; } + int k; +}; + +struct S { + constexpr S(int n) : k(2*n + 1) {} + constexpr operator int() { return k; } + constexpr operator T() { return T(k); } + int k; +}; + +constexpr bool check(T a, T b) { return a == b.k; } + +static_assert(S(5) == 11, ""); +static_assert(check(S(5), 11), ""); + +} + +} + +namespace Temporaries { + +struct S { + constexpr S() {} + constexpr int f(); +}; +struct T : S { + constexpr T(int n) : S(), n(n) {} + int n; +}; +constexpr int S::f() { + // 'this' must be the postfix-expression in a class member access expression, + // so we can't just use + // return static_cast<T*>(this)->n; + return this->*(int(S::*))&T::n; +} +// The T temporary is implicitly cast to an S subobject, but we can recover the +// T full-object via a base-to-derived cast, or a derived-to-base-casted member +// pointer. +static_assert(T(3).f() == 3, ""); + +constexpr int f(const S &s) { + return static_cast<const T&>(s).n; +} +constexpr int n = f(T(5)); +static_assert(f(T(5)) == 5, ""); + +constexpr bool b(int n) { return &n; } +static_assert(b(0), ""); + +} + +namespace Union { + +union U { + int a; + int b; +}; + +constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; // expected-warning 4{{C99 feature}} +static_assert(u[0].a == 0, ""); +static_assert(u[0].b, ""); // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}} +static_assert(u[1].b == 1, ""); +static_assert((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +static_assert(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} expected-note {{cannot refer to element 2 of non-array object}} +static_assert((&(u[1]) + 1 + 1)->b == 3, ""); + +constexpr U v = {}; +static_assert(v.a == 0, ""); + +union Empty {}; +constexpr Empty e = {}; + +// Make sure we handle trivial copy constructors for unions. +constexpr U x = {42}; +constexpr U y = x; +static_assert(y.a == 42, ""); +static_assert(y.b == 42, ""); // expected-error {{constant expression}} expected-note {{'b' of union with active member 'a'}} + +} + +namespace MemberPointer { + struct A { + constexpr A(int n) : n(n) {} + int n; + constexpr int f() { return n + 3; } + }; + constexpr A a(7); + static_assert(A(5).*&A::n == 5, ""); + static_assert((&a)->*&A::n == 7, ""); + static_assert((A(8).*&A::f)() == 11, ""); + static_assert(((&a)->*&A::f)() == 10, ""); + + struct B : A { + constexpr B(int n, int m) : A(n), m(m) {} + int m; + constexpr int g() { return n + m + 1; } + }; + constexpr B b(9, 13); + static_assert(B(4, 11).*&A::n == 4, ""); + static_assert(B(4, 11).*&B::m == 11, ""); + static_assert(B(4, 11).*(int(A::*))&B::m == 11, ""); + static_assert((&b)->*&A::n == 9, ""); + static_assert((&b)->*&B::m == 13, ""); + static_assert((&b)->*(int(A::*))&B::m == 13, ""); + static_assert((B(4, 11).*&A::f)() == 7, ""); + static_assert((B(4, 11).*&B::g)() == 16, ""); + static_assert((B(4, 11).*(int(A::*)()const)&B::g)() == 16, ""); + static_assert(((&b)->*&A::f)() == 12, ""); + static_assert(((&b)->*&B::g)() == 23, ""); + static_assert(((&b)->*(int(A::*)()const)&B::g)() == 23, ""); + + struct S { + constexpr S(int m, int n, int (S::*pf)() const, int S::*pn) : + m(m), n(n), pf(pf), pn(pn) {} + constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {} + + constexpr int f() { return this->*pn; } + virtual int g() const; + + int m, n; + int (S::*pf)() const; + int S::*pn; + }; + + constexpr int S::*pm = &S::m; + constexpr int S::*pn = &S::n; + constexpr int (S::*pf)() const = &S::f; + constexpr int (S::*pg)() const = &S::g; + + constexpr S s(2, 5, &S::f, &S::m); + + static_assert((s.*&S::f)() == 2, ""); + static_assert((s.*s.pf)() == 2, ""); + + static_assert(pf == &S::f, ""); + static_assert(pf == s.*&S::pf, ""); + static_assert(pm == &S::m, ""); + static_assert(pm != pn, ""); + static_assert(s.pn != pn, ""); + static_assert(s.pn == pm, ""); + static_assert(pg != nullptr, ""); + static_assert(pf != nullptr, ""); + static_assert((int S::*)nullptr == nullptr, ""); + static_assert(pg == pg, ""); // expected-error {{constant expression}} expected-note {{comparison of pointer to virtual member function 'g' has unspecified value}} + static_assert(pf != pg, ""); // expected-error {{constant expression}} expected-note {{comparison of pointer to virtual member function 'g' has unspecified value}} + + template<int n> struct T : T<n-1> {}; + template<> struct T<0> { int n; }; + template<> struct T<30> : T<29> { int m; }; + + T<17> t17; + T<30> t30; + + constexpr int (T<10>::*deepn) = &T<0>::n; + static_assert(&(t17.*deepn) == &t17.n, ""); + static_assert(deepn == &T<2>::n, ""); + + constexpr int (T<15>::*deepm) = (int(T<10>::*))&T<30>::m; + constexpr int *pbad = &(t17.*deepm); // expected-error {{constant expression}} + static_assert(&(t30.*deepm) == &t30.m, ""); + static_assert(deepm == &T<50>::m, ""); + static_assert(deepm != deepn, ""); + + constexpr T<5> *p17_5 = &t17; + constexpr T<13> *p17_13 = (T<13>*)p17_5; + constexpr T<23> *p17_23 = (T<23>*)p17_13; // expected-error {{constant expression}} expected-note {{cannot cast object of dynamic type 'T<17>' to type 'T<23>'}} + static_assert(&(p17_5->*(int(T<3>::*))deepn) == &t17.n, ""); + static_assert(&(p17_13->*deepn) == &t17.n, ""); + constexpr int *pbad2 = &(p17_13->*(int(T<9>::*))deepm); // expected-error {{constant expression}} + + constexpr T<5> *p30_5 = &t30; + constexpr T<23> *p30_23 = (T<23>*)p30_5; + constexpr T<13> *p30_13 = p30_23; + static_assert(&(p30_5->*(int(T<3>::*))deepn) == &t30.n, ""); + static_assert(&(p30_13->*deepn) == &t30.n, ""); + static_assert(&(p30_23->*deepn) == &t30.n, ""); + static_assert(&(p30_5->*(int(T<2>::*))deepm) == &t30.m, ""); + static_assert(&(((T<17>*)p30_13)->*deepm) == &t30.m, ""); + static_assert(&(p30_23->*deepm) == &t30.m, ""); + + struct Base { int n; }; + template<int N> struct Mid : Base {}; + struct Derived : Mid<0>, Mid<1> {}; + static_assert(&Mid<0>::n == &Mid<1>::n, ""); + static_assert((int Derived::*)(int Mid<0>::*)&Mid<0>::n != + (int Derived::*)(int Mid<1>::*)&Mid<1>::n, ""); + static_assert(&Mid<0>::n == (int Mid<0>::*)&Base::n, ""); +} + +namespace ArrayBaseDerived { + + struct Base { + constexpr Base() {} + int n = 0; + }; + struct Derived : Base { + constexpr Derived() {} + constexpr const int *f() { return &n; } + }; + + constexpr Derived a[10]; + constexpr Derived *pd3 = const_cast<Derived*>(&a[3]); + constexpr Base *pb3 = const_cast<Derived*>(&a[3]); + static_assert(pb3 == pd3, ""); + + // pb3 does not point to an array element. + constexpr Base *pb4 = pb3 + 1; // ok, one-past-the-end pointer. + constexpr int pb4n = pb4->n; // expected-error {{constant expression}} expected-note {{cannot access field of pointer past the end}} + constexpr Base *err_pb5 = pb3 + 2; // expected-error {{constant expression}} expected-note {{cannot refer to element 2}} expected-note {{here}} + constexpr int err_pb5n = err_pb5->n; // expected-error {{constant expression}} expected-note {{initializer of 'err_pb5' is not a constant expression}} + constexpr Base *err_pb2 = pb3 - 1; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} expected-note {{here}} + constexpr int err_pb2n = err_pb2->n; // expected-error {{constant expression}} expected-note {{initializer of 'err_pb2'}} + constexpr Base *pb3a = pb4 - 1; + + // pb4 does not point to a Derived. + constexpr Derived *err_pd4 = (Derived*)pb4; // expected-error {{constant expression}} expected-note {{cannot access derived class of pointer past the end}} + constexpr Derived *pd3a = (Derived*)pb3a; + constexpr int pd3n = pd3a->n; + + // pd3a still points to the Derived array. + constexpr Derived *pd6 = pd3a + 3; + static_assert(pd6 == &a[6], ""); + constexpr Derived *pd9 = pd6 + 3; + constexpr Derived *pd10 = pd6 + 4; + constexpr int pd9n = pd9->n; // ok + constexpr int err_pd10n = pd10->n; // expected-error {{constant expression}} expected-note {{cannot access base class of pointer past the end}} + constexpr int pd0n = pd10[-10].n; + constexpr int err_pdminus1n = pd10[-11].n; // expected-error {{constant expression}} expected-note {{cannot refer to element -1 of}} + + constexpr Base *pb9 = pd9; + constexpr const int *(Base::*pfb)() const = + static_cast<const int *(Base::*)() const>(&Derived::f); + static_assert((pb9->*pfb)() == &a[9].n, ""); +} + +namespace Complex { + +class complex { + int re, im; +public: + constexpr complex(int re = 0, int im = 0) : re(re), im(im) {} + constexpr complex(const complex &o) : re(o.re), im(o.im) {} + constexpr complex operator-() const { return complex(-re, -im); } + friend constexpr complex operator+(const complex &l, const complex &r) { + return complex(l.re + r.re, l.im + r.im); + } + friend constexpr complex operator-(const complex &l, const complex &r) { + return l + -r; + } + friend constexpr complex operator*(const complex &l, const complex &r) { + return complex(l.re * r.re - l.im * r.im, l.re * r.im + l.im * r.re); + } + friend constexpr bool operator==(const complex &l, const complex &r) { + return l.re == r.re && l.im == r.im; + } + constexpr bool operator!=(const complex &r) const { + return re != r.re || im != r.im; + } + constexpr int real() const { return re; } + constexpr int imag() const { return im; } +}; + +constexpr complex i = complex(0, 1); +constexpr complex k = (3 + 4*i) * (6 - 4*i); +static_assert(complex(1,0).real() == 1, ""); +static_assert(complex(1,0).imag() == 0, ""); +static_assert(((complex)1).imag() == 0, ""); +static_assert(k.real() == 34, ""); +static_assert(k.imag() == 12, ""); +static_assert(k - 34 == 12*i, ""); +static_assert((complex)1 == complex(1), ""); +static_assert((complex)1 != complex(0, 1), ""); +static_assert(complex(1) == complex(1), ""); +static_assert(complex(1) != complex(0, 1), ""); +constexpr complex makeComplex(int re, int im) { return complex(re, im); } +static_assert(makeComplex(1,0) == complex(1), ""); +static_assert(makeComplex(1,0) != complex(0, 1), ""); + +class complex_wrap : public complex { +public: + constexpr complex_wrap(int re, int im = 0) : complex(re, im) {} + constexpr complex_wrap(const complex_wrap &o) : complex(o) {} +}; + +static_assert((complex_wrap)1 == complex(1), ""); +static_assert((complex)1 != complex_wrap(0, 1), ""); +static_assert(complex(1) == complex_wrap(1), ""); +static_assert(complex_wrap(1) != complex(0, 1), ""); +constexpr complex_wrap makeComplexWrap(int re, int im) { + return complex_wrap(re, im); +} +static_assert(makeComplexWrap(1,0) == complex(1), ""); +static_assert(makeComplexWrap(1,0) != complex(0, 1), ""); + +} + +namespace PR11595 { + struct A { constexpr bool operator==(int x) { return true; } }; + struct B { B(); A& x; }; + static_assert(B().x == 3, ""); // expected-error {{constant expression}} expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}} + + constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}} + return B().x == k; // expected-note {{non-literal type 'PR11595::B' cannot be used in a constant expression}} + } +} + +namespace ExprWithCleanups { + struct A { A(); ~A(); int get(); }; + constexpr int get(bool FromA) { return FromA ? A().get() : 1; } + constexpr int n = get(false); +} + +namespace Volatile { + +volatile constexpr int n1 = 0; // expected-note {{here}} +volatile const int n2 = 0; // expected-note {{here}} +int n3 = 37; // expected-note {{declared here}} + +constexpr int m1 = n1; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} +constexpr int m2 = n2; // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}} +constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}} +constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}} + +struct T { int n; }; +const T t = { 42 }; // expected-note {{declared here}} + +constexpr int f(volatile int &&r) { + return r; // expected-note {{read of volatile-qualified type 'volatile int'}} +} +constexpr int g(volatile int &&r) { + return const_cast<int&>(r); // expected-note {{read of volatile temporary is not allowed in a constant expression}} +} +struct S { + int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}} + int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}} + int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}} + int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}} +}; + +} + +namespace ExternConstexpr { + extern constexpr int n = 0; + extern constexpr int m; // expected-error {{constexpr variable declaration must be a definition}} + void f() { + extern constexpr int i; // expected-error {{constexpr variable declaration must be a definition}} + constexpr int j = 0; + constexpr int k; // expected-error {{default initialization of an object of const type}} + } +} + +namespace ComplexConstexpr { + constexpr _Complex float test1 = {}; + constexpr _Complex float test2 = {1}; + constexpr _Complex double test3 = {1,2}; + constexpr _Complex int test4 = {4}; + constexpr _Complex int test5 = 4; + constexpr _Complex int test6 = {5,6}; + typedef _Complex float fcomplex; + constexpr fcomplex test7 = fcomplex(); + + constexpr const double &t2r = __real test3; + constexpr const double &t2i = __imag test3; + static_assert(&t2r + 1 == &t2i, ""); + static_assert(t2r == 1.0, ""); + static_assert(t2i == 2.0, ""); + constexpr const double *t2p = &t2r; + static_assert(t2p[-1] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element -1 of array of 2 elements}} + static_assert(t2p[0] == 1.0, ""); + static_assert(t2p[1] == 2.0, ""); + static_assert(t2p[2] == 0.0, ""); // expected-error {{constant expr}} expected-note {{one-past-the-end pointer}} + static_assert(t2p[3] == 0.0, ""); // expected-error {{constant expr}} expected-note {{cannot refer to element 3 of array of 2 elements}} + constexpr _Complex float *p = 0; + constexpr float pr = __real *p; // expected-error {{constant expr}} expected-note {{cannot access real component of null}} + constexpr float pi = __imag *p; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of null}} + constexpr const _Complex double *q = &test3 + 1; + constexpr double qr = __real *q; // expected-error {{constant expr}} expected-note {{cannot access real component of pointer past the end}} + constexpr double qi = __imag *q; // expected-error {{constant expr}} expected-note {{cannot access imaginary component of pointer past the end}} + + static_assert(__real test6 == 5, ""); + static_assert(__imag test6 == 6, ""); + static_assert(&__imag test6 == &__real test6 + 1, ""); +} + +namespace InstantiateCaseStmt { + template<int x> constexpr int f() { return x; } + template<int x> int g(int c) { switch(c) { case f<x>(): return 1; } return 0; } + int gg(int c) { return g<4>(c); } +} + +namespace ConvertedConstantExpr { + extern int &m; + extern int &n; + + constexpr int k = 4; + int &m = const_cast<int&>(k); + + // If we have nothing more interesting to say, ensure we don't produce a + // useless note and instead just point to the non-constant subexpression. + enum class E { + em = m, + en = n, // expected-error {{not a constant expression}} + eo = (m + + n // expected-error {{not a constant expression}} + ), + eq = reinterpret_cast<int>((int*)0) // expected-error {{not a constant expression}} expected-note {{reinterpret_cast}} + }; +} + +namespace IndirectField { + struct S { + struct { // expected-warning {{GNU extension}} + union { + struct { // expected-warning {{GNU extension}} + int a; + int b; + }; + int c; + }; + int d; + }; + union { + int e; + int f; + }; + constexpr S(int a, int b, int d, int e) : a(a), b(b), d(d), e(e) {} + constexpr S(int c, int d, int f) : c(c), d(d), f(f) {} + }; + + constexpr S s1(1, 2, 3, 4); + constexpr S s2(5, 6, 7); + + // FIXME: The diagnostics here do a very poor job of explaining which unnamed + // member is active and which is requested. + static_assert(s1.a == 1, ""); + static_assert(s1.b == 2, ""); + static_assert(s1.c == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} + static_assert(s1.d == 3, ""); + static_assert(s1.e == 4, ""); + static_assert(s1.f == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} + + static_assert(s2.a == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} + static_assert(s2.b == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} + static_assert(s2.c == 5, ""); + static_assert(s2.d == 6, ""); + static_assert(s2.e == 0, ""); // expected-error {{constant expression}} expected-note {{union with active member}} + static_assert(s2.f == 7, ""); +} + +// DR1405: don't allow reading mutable members in constant expressions. +namespace MutableMembers { + struct MM { + mutable int n; // expected-note 3{{declared here}} + } constexpr mm = { 4 }; + constexpr int mmn = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}} + int x = (mm.n = 1, 3); + constexpr int mmn2 = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}} + + // Here's one reason why allowing this would be a disaster... + template<int n> struct Id { int k = n; }; + int f() { + constexpr MM m = { 0 }; + ++m.n; + return Id<m.n>().k; // expected-error {{not a constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}} + } + + struct A { int n; }; + struct B { mutable A a; }; // expected-note {{here}} + struct C { B b; }; + constexpr C c[3] = {}; + constexpr int k = c[1].b.a.n; // expected-error {{constant expression}} expected-note {{mutable}} +} + +namespace Fold { + + // This macro forces its argument to be constant-folded, even if it's not + // otherwise a constant expression. + #define fold(x) (__builtin_constant_p(x) ? (x) : (x)) + + constexpr int n = (int)(char*)123; // expected-error {{constant expression}} expected-note {{reinterpret_cast}} + constexpr int m = fold((int)(char*)123); // ok + static_assert(m == 123, ""); + + #undef fold + +} + +namespace DR1454 { + +constexpr const int &f(const int &n) { return n; } +constexpr int k1 = f(0); // ok + +struct Wrap { + const int &value; +}; +constexpr const Wrap &g(const Wrap &w) { return w; } +constexpr int k2 = g({0}).value; // ok + +constexpr const int &i = 0; // expected-error {{constant expression}} expected-note {{temporary}} expected-note 2{{here}} +constexpr const int j = i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}} + +} + +namespace RecursiveOpaqueExpr { + template<typename Iter> + constexpr auto LastNonzero(Iter p, Iter q) -> decltype(+*p) { + return p != q ? (LastNonzero(p+1, q) ?: *p) : 0; // expected-warning {{GNU}} + } + + constexpr int arr1[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 0 }; + static_assert(LastNonzero(begin(arr1), end(arr1)) == 4, ""); + + constexpr int arr2[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 5 }; + static_assert(LastNonzero(begin(arr2), end(arr2)) == 5, ""); +} + +namespace VLASizeof { + + void f(int k) { + int arr[k]; // expected-warning {{C99}} + constexpr int n = 1 + + sizeof(arr) // expected-error {{constant expression}} + * 3; + } +} + +namespace CompoundLiteral { + // FIXME: + // We don't model the semantics of this correctly: the compound literal is + // represented as a prvalue in the AST, but actually behaves like an lvalue. + // We treat the compound literal as a temporary and refuse to produce a + // pointer to it. This is OK: we're not required to treat this as a constant + // in C++, and in C we model compound literals as lvalues. + constexpr int *p = (int*)(int[1]){0}; // expected-warning {{C99}} expected-error {{constant expression}} expected-note 2{{temporary}} +} + +namespace Vector { + typedef int __attribute__((vector_size(16))) VI4; + constexpr VI4 f(int n) { + return VI4 { n * 3, n + 4, n - 5, n / 6 }; + } + constexpr auto v1 = f(10); + + typedef double __attribute__((vector_size(32))) VD4; + constexpr VD4 g(int n) { + return (VD4) { n / 2.0, n + 1.5, n - 5.4, n * 0.9 }; // expected-warning {{C99}} + } + constexpr auto v2 = g(4); +} diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp index 1341036..23a4dda 100644 --- a/test/SemaCXX/constant-expression.cpp +++ b/test/SemaCXX/constant-expression.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %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 @@ -85,3 +85,35 @@ enum { a = sizeof(int) == 8, b = a? 8 : 4 }; + +void diags(int n) { + switch (n) { + case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} + case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} + case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} + case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} + ; + } +} + +namespace IntOrEnum { + const int k = 0; + const int &p = k; + template<int n> struct S {}; + S<p> s; // expected-error {{not an integral constant expression}} +} + +extern const int recurse1; +// recurse2 cannot be used in a constant expression because it is not +// initialized by a constant expression. The same expression appearing later in +// the TU would be a constant expression, but here it is not. +const int recurse2 = recurse1; +const int recurse1 = 1; +int array1[recurse1]; // ok +int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}} + +namespace FloatConvert { + typedef int a[(int)42.3]; + typedef int a[(int)42.997]; + typedef int b[(int)4e10]; // expected-warning {{variable length}} expected-error {{variable length}} +} diff --git a/test/SemaCXX/constexpr-ackermann.cpp b/test/SemaCXX/constexpr-ackermann.cpp new file mode 100644 index 0000000..c4ea313 --- /dev/null +++ b/test/SemaCXX/constexpr-ackermann.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +constexpr unsigned long long A(unsigned long long m, unsigned long long n) { + return m == 0 ? n + 1 : n == 0 ? A(m-1, 1) : A(m - 1, A(m, n - 1)); +} + +using X = int[A(3,4)]; +using X = int[125]; diff --git a/test/SemaCXX/constexpr-backtrace-limit.cpp b/test/SemaCXX/constexpr-backtrace-limit.cpp new file mode 100644 index 0000000..9c40eed --- /dev/null +++ b/test/SemaCXX/constexpr-backtrace-limit.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 0 -fconstexpr-depth 4 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST1 +// TEST1: constant expression +// TEST1-NEXT: exceeded maximum depth of 4 +// TEST1-NEXT: in call to 'recurse(2)' +// TEST1-NEXT: in call to 'recurse(3)' +// TEST1-NEXT: in call to 'recurse(4)' +// TEST1-NEXT: in call to 'recurse(5)' + +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 2 -fconstexpr-depth 4 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST2 +// TEST2: constant expression +// TEST2-NEXT: exceeded maximum depth of 4 +// TEST2-NEXT: in call to 'recurse(2)' +// TEST2-NEXT: skipping 2 calls +// TEST2-NEXT: in call to 'recurse(5)' + +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 2 -fconstexpr-depth 8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST3 +// TEST3: constant expression +// TEST3-NEXT: reinterpret_cast +// TEST3-NEXT: in call to 'recurse(0)' +// TEST3-NEXT: skipping 4 calls +// TEST3-NEXT: in call to 'recurse(5)' + +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -fconstexpr-backtrace-limit 8 -fconstexpr-depth 8 -fno-caret-diagnostics 2>&1 | FileCheck %s -check-prefix=TEST4 +// TEST4: constant expression +// TEST4-NEXT: reinterpret_cast +// TEST4-NEXT: in call to 'recurse(0)' +// TEST4-NEXT: in call to 'recurse(1)' +// TEST4-NEXT: in call to 'recurse(2)' +// TEST4-NEXT: in call to 'recurse(3)' +// TEST4-NEXT: in call to 'recurse(4)' +// TEST4-NEXT: in call to 'recurse(5)' + +constexpr int recurse(int n) { return n ? recurse(n-1) : *(int*)n; } +static_assert(recurse(5), ""); diff --git a/test/SemaCXX/constexpr-depth.cpp b/test/SemaCXX/constexpr-depth.cpp new file mode 100644 index 0000000..feba6fd --- /dev/null +++ b/test/SemaCXX/constexpr-depth.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=128 -fconstexpr-depth 128 +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=2 -fconstexpr-depth 2 +// RUN: %clang -std=c++11 -fsyntax-only -Xclang -verify %s -DMAX=10 -fconstexpr-depth=10 + +constexpr int depth(int n) { return n > 1 ? depth(n-1) : 0; } // expected-note {{exceeded maximum depth}} expected-note +{{}} + +constexpr int kBad = depth(MAX + 1); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'depth(}} +constexpr int kGood = depth(MAX); diff --git a/test/SemaCXX/constexpr-factorial.cpp b/test/SemaCXX/constexpr-factorial.cpp new file mode 100644 index 0000000..b6cdde5 --- /dev/null +++ b/test/SemaCXX/constexpr-factorial.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +constexpr unsigned oddfac(unsigned n) { + return n == 1 ? 1 : n * oddfac(n-2); +} +constexpr unsigned k = oddfac(123); + +using A = int[k % 256]; +using A = int[43]; diff --git a/test/SemaCXX/constexpr-nqueens.cpp b/test/SemaCXX/constexpr-nqueens.cpp new file mode 100644 index 0000000..b158d6e --- /dev/null +++ b/test/SemaCXX/constexpr-nqueens.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s + +typedef unsigned long uint64_t; + +struct Board { + uint64_t State; + bool Failed; + + constexpr Board() : State(0), Failed(false) {} + constexpr Board(const Board &O) : State(O.State), Failed(O.Failed) {} + constexpr Board(uint64_t State, bool Failed = false) : + State(State), Failed(Failed) {} + constexpr Board addQueen(int Row, int Col) { + return Board(State | ((uint64_t)Row << (Col * 4))); + } + constexpr int getQueenRow(int Col) { + return (State >> (Col * 4)) & 0xf; + } + constexpr bool ok(int Row, int Col) { + return okRecurse(Row, Col, 0); + } + constexpr bool okRecurse(int Row, int Col, int CheckCol) { + return Col == CheckCol ? true : + getQueenRow(CheckCol) == Row ? false : + getQueenRow(CheckCol) == Row + (Col - CheckCol) ? false : + getQueenRow(CheckCol) == Row + (CheckCol - Col) ? false : + okRecurse(Row, Col, CheckCol + 1); + } + constexpr bool at(int Row, int Col) { + return getQueenRow(Col) == Row; + } + constexpr bool check(const char *, int=0, int=0); +}; + +constexpr Board buildBoardRecurse(int N, int Col, const Board &B); +constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B); +constexpr Board tryBoard(const Board &Try, + int N, int Col, int Row, const Board &B) { + return Try.Failed ? buildBoardScan(N, Col, Row, B) : Try; +} +constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) { + return Row == N ? Board(0, true) : + B.ok(Row, Col) ? + tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), + N, Col, Row+1, B) : + buildBoardScan(N, Col, Row + 1, B); +} +constexpr Board buildBoardRecurse(int N, int Col, const Board &B) { + return Col == N ? B : buildBoardScan(N, Col, 0, B); +} +constexpr Board buildBoard(int N) { + return buildBoardRecurse(N, 0, Board()); +} + +constexpr Board q8 = buildBoard(8); + +constexpr bool Board::check(const char *p, int Row, int Col) { + return + *p == '\n' ? check(p+1, Row+1, 0) : + *p == 'o' ? at(Row, Col) && check(p+1, Row, Col+1) : + *p == '-' ? !at(Row, Col) && check(p+1, Row, Col+1) : + *p == 0 ? true : + false; +} +static_assert(q8.check( + "o-------\n" + "------o-\n" + "----o---\n" + "-------o\n" + "-o------\n" + "---o----\n" + "-----o--\n" + "--o-----\n"), ""); diff --git a/test/SemaCXX/constexpr-printing.cpp b/test/SemaCXX/constexpr-printing.cpp new file mode 100644 index 0000000..9170fa1 --- /dev/null +++ b/test/SemaCXX/constexpr-printing.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -triple x86_64-linux-gnu + +struct S; +constexpr int extract(const S &s); + +struct S { + constexpr S() : n(extract(*this)), m(0) {} // expected-note {{in call to 'extract(s1)'}} + constexpr S(int k) : n(k), m(extract(*this)) {} + int n, m; +}; + +constexpr int extract(const S &s) { return s.n; } // expected-note {{read of uninitialized object is not allowed in a constant expression}} + +constexpr S s1; // ok +void f() { + constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}} + constexpr S s2(10); +} + +typedef __attribute__((vector_size(16))) int vector_int; + +struct T { + constexpr T() : arr() {} + int arr[4]; +}; +struct U : T { + constexpr U(const int *p) : T(), another(), p(p) {} + constexpr U(const U &u) : T(), another(), p(u.p) {} + T another; + const int *p; +}; +constexpr U u1(&u1.arr[2]); + +constexpr int test_printing(int a, float b, _Complex int c, _Complex float d, + int *e, int &f, vector_int g, U h) { + return *e; // expected-note {{read of non-constexpr variable 'u2'}} +} +U u2(0); // expected-note {{here}} +static_assert(test_printing(12, 39.762, 3 + 4i, 12.9 + 3.6i, &u2.arr[4], u2.another.arr[2], (vector_int){5, 1, 2, 3}, u1) == 0, ""); // \ +expected-error {{constant expression}} \ +expected-note {{in call to 'test_printing(12, 3.976200e+01, 3+4i, 1.290000e+01+3.600000e+00i, &u2.T::arr[4], u2.another.arr[2], {5, 1, 2, 3}, {{{}}, {{}}, &u1.T::arr[2]})'}} + +struct V { + // FIXME: when we can generate these as constexpr constructors, remove the + // explicit definitions. + constexpr V() : arr{[255] = 42} {} + constexpr V(const V &v) : arr{[255] = 42} {} + int arr[256]; +}; +constexpr V v; +constexpr int get(const int *p) { return *p; } // expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr int passLargeArray(V v) { return get(v.arr+256); } // expected-note {{in call to 'get(&v.arr[256])'}} +static_assert(passLargeArray(v) == 0, ""); // expected-error {{constant expression}} expected-note {{in call to 'passLargeArray({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...}})'}} + +union Union { + constexpr Union(int n) : b(n) {} + constexpr Union(const Union &u) : b(u.b) {} + int a, b; +}; +constexpr Union myUnion = 76; + +constexpr int badness(Union u) { return u.a + u.b; } // expected-note {{read of member 'a' of union with active member 'b'}} +static_assert(badness(myUnion), ""); // expected-error {{constant expression}} \ + expected-note {{in call to 'badness({.b = 76})'}} + +struct MemPtrTest { + int n; + void f(); +}; +MemPtrTest mpt; // expected-note {{here}} +constexpr int MemPtr(int (MemPtrTest::*a), void (MemPtrTest::*b)(), int &c) { + return c; // expected-note {{read of non-constexpr variable 'mpt'}} +} +static_assert(MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.*&MemPtrTest::n), ""); // expected-error {{constant expression}} \ +expected-note {{in call to 'MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.n)'}} + +template<typename CharT> +constexpr CharT get(const CharT *p) { return p[-1]; } // expected-note 5{{}} + +constexpr char c = get("test\0\\\"\t\a\b\234"); // \ + expected-error {{}} expected-note {{"test\000\\\"\t\a\b\234"}} +constexpr char c8 = get(u8"test\0\\\"\t\a\b\234"); // \ + expected-error {{}} expected-note {{u8"test\000\\\"\t\a\b\234"}} +constexpr char16_t c16 = get(u"test\0\\\"\t\a\b\234\u1234"); // \ + expected-error {{}} expected-note {{u"test\000\\\"\t\a\b\234\u1234"}} +constexpr char32_t c32 = get(U"test\0\\\"\t\a\b\234\u1234\U0010ffff"); // \ + expected-error {{}} expected-note {{U"test\000\\\"\t\a\b\234\u1234\U0010FFFF"}} +constexpr wchar_t wc = get(L"test\0\\\"\t\a\b\234\u1234\xffffffff"); // \ + expected-error {{}} expected-note {{L"test\000\\\"\t\a\b\234\x1234\xFFFFFFFF"}} + +constexpr char32_t c32_err = get(U"\U00110000"); // expected-error {{invalid universal character}} + +typedef decltype(sizeof(int)) LabelDiffTy; +constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } // expected-note {{subexpression}} +void LabelDiffTest() { + static_assert(mulBy3((LabelDiffTy)&&a-(LabelDiffTy)&&b) == 3, ""); // expected-error {{constant expression}} expected-note {{call to 'mulBy3(&&a - &&b)'}} + a:b:return; +} + +constexpr bool test_bool_printing(bool b) { return 1 / !(2*b | !(2*b)); } // expected-note 2{{division by zero}} +constexpr bool test_bool_0 = test_bool_printing(false); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(false)'}} +constexpr bool test_bool_1 = test_bool_printing(true); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(true)'}} diff --git a/test/SemaCXX/constexpr-strlen.cpp b/test/SemaCXX/constexpr-strlen.cpp new file mode 100644 index 0000000..5e28e7f --- /dev/null +++ b/test/SemaCXX/constexpr-strlen.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -pedantic + +# 1 "/usr/include/string.h" 1 3 4 +extern "C" { + typedef decltype(sizeof(int)) size_t; + extern size_t strlen(const char *p); +} + +# 10 "SemaCXX/constexpr-strlen.cpp" 2 +constexpr int n = __builtin_strlen("hello"); // ok +constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}} + +// Make sure we can evaluate a call to strlen. +int arr[3]; // expected-note {{here}} +int k = arr[strlen("hello")]; // expected-warning {{array index 5}} diff --git a/test/SemaCXX/constexpr-turing.cpp b/test/SemaCXX/constexpr-turing.cpp new file mode 100644 index 0000000..c515378 --- /dev/null +++ b/test/SemaCXX/constexpr-turing.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +// A direct proof that constexpr is Turing-complete, once DR1454 is implemented. + +const unsigned halt = (unsigned)-1; + +enum Dir { L, R }; +struct Action { + bool tape; + Dir dir; + unsigned next; +}; +using State = Action[2]; + +// An infinite tape! +struct Tape { + constexpr Tape() : l(0), val(false), r(0) {} + constexpr Tape(const Tape &old, bool write) : + l(old.l), val(write), r(old.r) {} + constexpr Tape(const Tape &old, Dir dir) : + l(dir == L ? old.l ? old.l->l : 0 : &old), + val(dir == L ? old.l ? old.l->val : false + : old.r ? old.r->val : false), + r(dir == R ? old.r ? old.r->r : 0 : &old) {} + const Tape *l; + bool val; + const Tape *r; +}; +constexpr Tape update(const Tape &old, bool write) { return Tape(old, write); } +constexpr Tape move(const Tape &old, Dir dir) { return Tape(old, dir); } + +// Run turing machine 'tm' on tape 'tape' from state 'state'. Return number of +// steps taken until halt. +constexpr unsigned run(const State *tm, const Tape &tape, unsigned state) { + return state == halt ? 1 : + run(tm, move(update(tape, tm[state][tape.val].tape), + tm[state][tape.val].dir), + tm[state][tape.val].next) + 1; +} + +// 3-state busy beaver. 14 steps. +constexpr State bb3[] = { + { { true, R, 1 }, { true, L, 2 } }, + { { true, L, 0 }, { true, R, 1 } }, + { { true, L, 1 }, { true, R, halt } } +}; +static_assert(run(bb3, Tape(), 0) == 14, ""); + +// 4-state busy beaver. 108 steps. +constexpr State bb4[] = { + { { true, R, 1 }, { true, L, 1 } }, + { { true, L, 0 }, { false, L, 2 } }, + { { true, R, halt }, { true, L, 3 } }, + { { true, R, 3 }, { false, R, 0 } } }; +static_assert(run(bb4, Tape(), 0) == 108, ""); diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp new file mode 100644 index 0000000..e459f09 --- /dev/null +++ b/test/SemaCXX/constexpr-value-init.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify + +struct A { + constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{uninitialized}} + int a; + int b; +}; +struct B { + A a; +}; + +constexpr A a; // ok, zero initialization preceeds static initialization +void f() { + constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}} +} + +constexpr B b1; // expected-error {{requires a user-provided default constructor}} +constexpr B b2 = B(); // ok +static_assert(b2.a.a == 1, ""); +static_assert(b2.a.b == 2, ""); + +struct C { + int c; +}; +struct D : C { int d; }; +constexpr C c1; // expected-error {{requires a user-provided default constructor}} +constexpr C c2 = C(); // ok +constexpr D d1; // expected-error {{requires a user-provided default constructor}} +constexpr D d2 = D(); // ok with DR1452 +static_assert(D().c == 0, ""); +static_assert(D().d == 0, ""); + +struct V : virtual C {}; +template<typename T> struct Z : T { + constexpr Z() : V() {} +}; +constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{virtual base class}} diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index e439a76..e8b7f0b 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -74,7 +74,7 @@ class U { union { int b; double d; }; U() : a(1), // expected-note {{previous initialization is here}} - p(0), // expected-error {{initializing multiple members of anonymous union}} + p(0), // expected-error {{initializing multiple members of union}} d(1.0) {} }; @@ -268,3 +268,15 @@ struct S4 { }; } + +namespace PR12049 { + int function(); + + class Class + { + public: + Class() : member(function() {} // expected-note {{to match this '('}} + + int member; // expected-error {{expected ')'}} + }; +} diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index b069abc..a64b187 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fsyntax-only -Wconversion %s 2>&1 | FileCheck %s #include <stddef.h> @@ -53,11 +54,30 @@ namespace test2 { }; } +// This file tests -Wnull-conversion, a subcategory of -Wconversion +// which is on by default. + void test3() { - int a = NULL; // expected-warning {{implicit conversion of NULL constant to integer}} + int a = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} 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}} + b = NULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} + long l = NULL; // FIXME: this should also warn, but currently does not if sizeof(NULL)==sizeof(inttype) + int c = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} int d; - d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to integer}} + d = ((((NULL)))); // expected-warning {{implicit conversion of NULL constant to 'int'}} + bool bl = NULL; // FIXME: this should warn but we currently suppress a bunch of conversion-to-bool warnings including this one + char ch = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}} + unsigned char uch = NULL; // expected-warning {{implicit conversion of NULL constant to 'unsigned char'}} + short sh = NULL; // expected-warning {{implicit conversion of NULL constant to 'short'}} + + // Use FileCheck to ensure we don't get any unnecessary macro-expansion notes + // (that don't appear as 'real' notes & can't be seen/tested by -verify) + // CHECK-NOT: note: + // CHECK: note: expanded from macro 'FNULL' +#define FNULL NULL + int a2 = FNULL; // expected-warning {{implicit conversion of NULL constant to 'int'}} + // CHECK-NOT: note: + // CHECK: note: expanded from macro 'FINIT' +#define FINIT int a3 = NULL; + FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}} } diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp index 7aca9d6..798582c 100644 --- a/test/SemaCXX/copy-assignment.cpp +++ b/test/SemaCXX/copy-assignment.cpp @@ -98,18 +98,13 @@ void test() { } // <rdar://problem/8315440>: Don't crash -// FIXME: the recovery here is really bad. namespace test1 { template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} - A(UndeclaredType n) : X(n) {} // expected-error{{expected ')'}} expected-note{{to match this '('}} \ - // expected-error{{use of undeclared identifier 'n'}} \ - // expected-error{{expected ';' at end of declaration list}} \ - // expected-error{{field has incomplete type 'test1::A<char>'}} + A(UndeclaredType n) : X(n) {} // expected-error {{unknown type name 'UndeclaredType'}} }; template<typename T> class B : public A<T> { virtual void foo() {} }; - extern template class A<char>; // expected-note {{in instantiation of template class 'test1::A<char>' requested here}} \ - // expected-note {{definition of 'test1::A<char>' is not complete until the closing '}'}} + extern template class A<char>; extern template class B<char>; } diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp index fb83dcf..ea2db0c 100644 --- a/test/SemaCXX/copy-initialization.cpp +++ b/test/SemaCXX/copy-initialization.cpp @@ -42,3 +42,26 @@ namespace PR6757 { f(foo); } } + +namespace DR5 { + // Core issue 5: if a temporary is created in copy-initialization, it is of + // the cv-unqualified version of the destination type. + namespace Ex1 { + struct C { }; + C c; + struct A { + A(const A&); + A(const C&); + }; + const volatile A a = c; // ok + } + + namespace Ex2 { + struct S { + S(S&&); // expected-warning {{C++11}} + S(int); + }; + const S a(0); + const S b = 0; + } +} diff --git a/test/SemaCXX/cxx0x-class.cpp b/test/SemaCXX/cxx0x-class.cpp index 3527ccb..41b0a5c 100644 --- a/test/SemaCXX/cxx0x-class.cpp +++ b/test/SemaCXX/cxx0x-class.cpp @@ -11,18 +11,29 @@ public: int i = 0; 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}} + static const int nci = vs; // expected-error {{in-class initializer for static data member is not a constant expression}} static const int vi = 0; static const volatile int cvi = 0; // expected-error {{static const volatile data member must be initialized out of line}} }; namespace rdar8367341 { - float foo(); + float foo(); // expected-note {{here}} struct A { static const float x = 5.0f; // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} - static const float y = foo(); // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} expected-error {{in-class initializer is not a constant expression}} + static const float y = foo(); // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} expected-error {{in-class initializer for static data member is not a constant expression}} static constexpr float x2 = 5.0f; - static constexpr float y2 = foo(); // expected-error {{must be initialized by a constant expression}} + static constexpr float y2 = foo(); // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr function 'foo'}} + }; +} + + +namespace Foo { + // Regression test -- forward declaration of Foo should not cause error about + // nonstatic data member. + class Foo; + class Foo { + int x; + int y = x; }; } diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp index a01b26c..123008a 100644 --- a/test/SemaCXX/cxx0x-compat.cpp +++ b/test/SemaCXX/cxx0x-compat.cpp @@ -1,18 +1,23 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++0x-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -verify %s namespace N { - template<typename T> void f(T) {} // expected-note {{here}} + template<typename T> void f(T) {} // expected-note 2{{here}} namespace M { - template void f<int>(int); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}} + template void ::N::f<int>(int); // expected-warning {{explicit instantiation of 'f' not in a namespace enclosing 'N'}} } } +using namespace N; +template void f<char>(char); // expected-warning {{explicit instantiation of 'N::f' must occur in namespace 'N'}} -template<typename T> void f(T) {} // expected-note {{here}} +template<typename T> void g(T) {} // expected-note 2{{here}} namespace M { - template void f<int>(int); // expected-warning {{explicit instantiation of 'f' must occur in the global namespace}} + template void g<int>(int); // expected-warning {{explicit instantiation of 'g' must occur at global scope}} + template void ::g<char>(char); // expected-warning {{explicit instantiation of 'g' must occur at global scope}} } -void f() { +template inline void g<double>(double); // expected-warning {{explicit instantiation cannot be 'inline'}} + +void g() { auto int n = 0; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} } @@ -22,3 +27,13 @@ struct S { } s = { n }, // expected-warning {{non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list in C++11}} expected-note {{explicit cast}} t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which cannot be narrowed to type 'char' in C++11}} expected-warning {{changes value}} expected-note {{explicit cast}} + +#define PRIuS "uS" +int printf(const char *, ...); +typedef __typeof(sizeof(int)) size_t; +void h(size_t foo, size_t bar) { + printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a reserved user-defined literal suffix in C++11}} +} + +#define _x + 1 +char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}} diff --git a/test/SemaCXX/cxx0x-cursory-default-delete.cpp b/test/SemaCXX/cxx0x-cursory-default-delete.cpp index 17933c2..3290595 100644 --- a/test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ b/test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -67,3 +67,9 @@ struct except_spec_d_mismatch : except_spec_a, except_spec_b { struct except_spec_d_match : except_spec_a, except_spec_b { except_spec_d_match() throw(A, B) = default; }; + +// gcc-compatibility: allow attributes on default definitions +// (but not normal definitions) +struct S { S(); }; +S::S() __attribute((pure)) = default; + diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp index d01f63b..2e4107c 100644 --- a/test/SemaCXX/cxx0x-defaulted-functions.cpp +++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp @@ -28,7 +28,7 @@ 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(__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), @@ -43,3 +43,11 @@ void tester() { b = c; } +template<typename T> struct S : T { + constexpr S() = default; + constexpr S(const S&) = default; + constexpr S(S&&) = default; +}; +struct lit { constexpr lit() {} }; +S<lit> s_lit; // ok +S<bar> s_bar; // ok diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index 16c5664..0cebc10 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -7,27 +7,27 @@ struct non_trivial { ~non_trivial(); }; -union bad_union { // expected-note {{marked deleted here}} - non_trivial nt; +union bad_union { + non_trivial nt; // expected-note {{non-trivial default constructor}} }; -bad_union u; // expected-error {{call to deleted constructor}} -union bad_union2 { // expected-note {{marked deleted here}} +bad_union u; // expected-error {{call to implicitly-deleted default constructor}} +union bad_union2 { // expected-note {{all data members are const-qualified}} const int i; }; -bad_union2 u2; // expected-error {{call to deleted constructor}} +bad_union2 u2; // expected-error {{call to implicitly-deleted default constructor}} -struct bad_anon { // expected-note {{marked deleted here}} +struct bad_anon { union { - non_trivial nt; + non_trivial nt; // expected-note {{non-trivial default constructor}} }; }; -bad_anon a; // expected-error {{call to deleted constructor}} -struct bad_anon2 { // expected-note {{marked deleted here}} - union { +bad_anon a; // expected-error {{call to implicitly-deleted default constructor}} +struct bad_anon2 { + union { // expected-note {{all data members of an anonymous union member are const-qualified}} const int i; }; }; -bad_anon2 a2; // expected-error {{call to deleted constructor}} +bad_anon2 a2; // expected-error {{call to implicitly-deleted default constructor}} // This would be great except that we implement union good_union { @@ -48,10 +48,10 @@ struct good : non_trivial { }; good g; -struct bad_const { // expected-note {{marked deleted here}} - const good g; +struct bad_const { + const good g; // expected-note {{field 'g' of const-qualified type 'const good' would not be initialized}} }; -bad_const bc; // expected-error {{call to deleted constructor}} +bad_const bc; // expected-error {{call to implicitly-deleted default constructor}} struct good_const { const non_trivial nt; @@ -59,44 +59,44 @@ struct good_const { good_const gc; struct no_default { - no_default() = delete; + no_default() = delete; // expected-note 3{{deleted here}} }; struct no_dtor { - ~no_dtor() = delete; + ~no_dtor() = delete; // expected-note 2{{deleted here}} }; -struct bad_field_default { // expected-note {{marked deleted here}} - no_default nd; +struct bad_field_default { + no_default nd; // expected-note {{field 'nd' has a deleted default constructor}} }; -bad_field_default bfd; // expected-error {{call to deleted constructor}} -struct bad_base_default : no_default { // expected-note {{marked deleted here}} +bad_field_default bfd; // expected-error {{call to implicitly-deleted default constructor}} +struct bad_base_default : no_default { // expected-note {{base class 'no_default' has a deleted default constructor}} }; -bad_base_default bbd; // expected-error {{call to deleted constructor}} +bad_base_default bbd; // expected-error {{call to implicitly-deleted default constructor}} -struct bad_field_dtor { // expected-note {{marked deleted here}} - no_dtor nd; +struct bad_field_dtor { + no_dtor nd; // expected-note {{field 'nd' has a deleted destructor}} }; -bad_field_dtor bfx; // expected-error {{call to deleted constructor}} -struct bad_base_dtor : no_dtor { // expected-note {{marked deleted here}} +bad_field_dtor bfx; // expected-error {{call to implicitly-deleted default constructor}} +struct bad_base_dtor : no_dtor { // expected-note {{base class 'no_dtor' has a deleted destructor}} }; -bad_base_dtor bbx; // expected-error {{call to deleted constructor}} +bad_base_dtor bbx; // expected-error {{call to implicitly-deleted default constructor}} struct ambiguous_default { ambiguous_default(); ambiguous_default(int = 2); }; -struct has_amb_field { // expected-note {{marked deleted here}} - ambiguous_default ad; +struct has_amb_field { + ambiguous_default ad; // expected-note {{field 'ad' has multiple default constructors}} }; -has_amb_field haf; // expected-error {{call to deleted constructor}} +has_amb_field haf; // expected-error {{call to implicitly-deleted default constructor}} class inaccessible_default { inaccessible_default(); }; -struct has_inacc_field { // expected-note {{marked deleted here}} - inaccessible_default id; +struct has_inacc_field { + inaccessible_default id; // expected-note {{field 'id' has an inaccessible default constructor}} }; -has_inacc_field hif; // expected-error {{call to deleted constructor}} +has_inacc_field hif; // expected-error {{call to implicitly-deleted default constructor}} class friend_default { friend struct has_friend; @@ -108,10 +108,10 @@ struct has_friend { has_friend hf; struct defaulted_delete { - no_default nd; - defaulted_delete() = default; // expected-note {{marked deleted here}} + no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}} + defaulted_delete() = default; // expected-note{{implicitly deleted here}} }; -defaulted_delete dd; // expected-error {{call to deleted constructor}} +defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}} struct late_delete { no_default nd; @@ -121,12 +121,11 @@ late_delete::late_delete() = default; // expected-error {{would delete it}} // See also rdar://problem/8125400. namespace empty { - static union {}; // expected-error {{deleted constructor}} expected-note {{here}} + static union {}; static union { union {}; }; static union { struct {}; }; static union { union { union {}; }; }; static union { union { struct {}; }; }; - static union { struct { union {}; }; }; // expected-error {{deleted constructor}} expected-note {{here}} + static union { struct { union {}; }; }; static union { struct { struct {}; }; }; } - diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp new file mode 100644 index 0000000..801a82f --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct one { char c[1]; }; +struct two { char c[2]; }; + +namespace aggregate { + // Direct list initialization does NOT allow braces to be elided! + struct S { + int ar[2]; + struct T { + int i1; + int i2; + } t; + struct U { + int i1; + } u[2]; + struct V { + int var[2]; + } v; + }; + + void bracing() { + S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error + S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced + S s3{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} + S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} + S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} + } + + void bracing_new() { + new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced + new S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} + new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} + new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} + } + + void bracing_construct() { + (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced + (void) S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} + (void) S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} + (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} + } + + struct String { + String(const char*); + }; + + struct A { + int m1; + int m2; + }; + + void function_call() { + void takes_A(A); + takes_A({1, 2}); + } + + struct B { + int m1; + String m2; + }; + + void overloaded_call() { + one overloaded(A); + two overloaded(B); + + static_assert(sizeof(overloaded({1, 2})) == sizeof(one), "bad overload"); + static_assert(sizeof(overloaded({1, "two"})) == sizeof(two), + "bad overload"); + // String is not default-constructible + static_assert(sizeof(overloaded({1})) == sizeof(one), "bad overload"); + } + + struct C { int a[2]; C():a({1, 2}) { } }; // expected-error {{parenthesized initialization of a member array is a GNU extension}} +} + +namespace array_explicit_conversion { + typedef int test1[2]; + typedef int test2[]; + template<int x> struct A { int a[x]; }; // expected-error {{'a' declared as an array with a negative size}} + typedef A<1> test3[]; + typedef A<-1> test4[]; + void f() { + (void)test1{1}; + (void)test2{1}; + (void)test3{{{1}}}; + (void)test4{{{1}}}; // expected-note {{in instantiation of template class 'array_explicit_conversion::A<-1>' requested here}} + } +} diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp new file mode 100644 index 0000000..09aca24 --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -0,0 +1,283 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct one { char c[1]; }; +struct two { char c[2]; }; + +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 objects { + + struct X1 { X1(int); }; + struct X2 { explicit X2(int); }; // expected-note {{constructor declared here}} + + template <int N> + struct A { + A() { static_assert(N == 0, ""); } + A(int, double) { static_assert(N == 1, ""); } + }; + + template <int N> + struct F { + F() { static_assert(N == 0, ""); } + F(int, double) { static_assert(N == 1, ""); } + F(std::initializer_list<int>) { static_assert(N == 3, ""); } + }; + + template <int N> + struct D { + D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}} + D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}} + }; + + template <int N> + struct E { + E(int, int) { static_assert(N == 0, ""); } + E(X1, int) { static_assert(N == 1, ""); } + }; + + void overload_resolution() { + { A<0> a{}; } + { A<0> a = {}; } + { A<1> a{1, 1.0}; } + { A<1> a = {1, 1.0}; } + + { F<0> f{}; } + { F<0> f = {}; } + // Narrowing conversions don't affect viability. The next two choose + // the initializer_list constructor. + // FIXME: Emit narrowing conversion errors. + { F<3> f{1, 1.0}; } // xpected-error {{narrowing conversion}} + { F<3> f = {1, 1.0}; } // xpected-error {{narrowing conversion}} + { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } + { F<3> f = {1, 2, 3, 4, 5, 6, 7, 8}; } + { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } + { F<3> f{1, 2}; } + + { D<0> d{1, 2, 3}; } + { D<1> d{1.0, 2.0, 3.0}; } + { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}} + + { E<0> e{1, 2}; } + } + + void explicit_implicit() { + { X1 x{0}; } + { X1 x = {0}; } + { X2 x{0}; } + { X2 x = {0}; } // expected-error {{constructor is explicit}} + } + + struct C { + C(); + C(int, double); + C(int, 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) C{1, 1.0}; + (void) new C{1, 1.0}; + (void) A<1>{1, 1.0}; + (void) new A<1>{1, 1.0}; + } + + struct B { // expected-note 2 {{candidate constructor}} + B(C, int, C); // expected-note {{candidate constructor not viable: cannot convert initializer list argument to 'objects::C'}} + }; + + void nested_init() { + B b1{{1, 1.0}, 2, {3, 4}}; + B b2{{1, 1.0, 4}, 2, {3, 4}}; // expected-error {{no matching constructor for initialization of 'objects::B'}} + } + + void overloaded_call() { + one ov1(B); // expected-note {{not viable: cannot convert initializer list}} + two ov1(C); // expected-note {{not viable: cannot convert initializer list}} + + static_assert(sizeof(ov1({})) == sizeof(two), "bad overload"); + static_assert(sizeof(ov1({1, 2})) == sizeof(two), "bad overload"); + static_assert(sizeof(ov1({{1, 1.0}, 2, {3, 4}})) == sizeof(one), "bad overload"); + + ov1({1}); // expected-error {{no matching function}} + + one ov2(int); + two ov2(F<3>); + static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity + static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable + } + + struct G { // expected-note 6 {{not viable}} + // This is not an initializer-list constructor. + template<typename ...T> + G(std::initializer_list<int>, T ...); // expected-note 3 {{not viable}} + }; + + struct H { // expected-note 6 {{not viable}} + explicit H(int, int); // expected-note 3 {{not viable}} expected-note {{declared here}} + H(int, void*); // expected-note 3 {{not viable}} + }; + + void edge_cases() { + // invalid (the first phase only considers init-list ctors) + // (for the second phase, no constructor is viable) + G g1{1, 2, 3}; // expected-error {{no matching constructor}} + (void) new G{1, 2, 3}; // expected-error {{no matching constructor}} + (void) G{1, 2, 3} // expected-error {{no matching constructor}} + + // valid (T deduced to <>). + G g2({1, 2, 3}); + (void) new G({1, 2, 3}); + (void) G({1, 2, 3}); + + // invalid + H h1({1, 2}); // expected-error {{no matching constructor}} + (void) new H({1, 2}); // expected-error {{no matching constructor}} + // FIXME: Bad diagnostic, mentions void type instead of init list. + (void) H({1, 2}); // expected-error {{no matching conversion}} + + // valid (by copy constructor). + H h2({1, nullptr}); + (void) new H({1, nullptr}); + (void) H({1, nullptr}); + + // valid + H h3{1, 2}; + (void) new H{1, 2}; + (void) H{1, 2}; + } + + struct memberinit { + H h1{1, nullptr}; + H h2 = {1, nullptr}; + H h3{1, 1}; + H h4 = {1, 1}; // expected-error {{constructor is explicit}} + }; +} + +namespace PR12092 { + + struct S { + S(const char*); + }; + struct V { + template<typename T> V(T, T); + void f(std::initializer_list<S>); + void f(const V &); + }; + + void g() { + extern V s; + s.f({"foo", "bar"}); + } + +} + +namespace PR12117 { + struct A { A(int); }; + struct B { B(A); } b{{0}}; + struct C { C(int); } c{0}; +} + +namespace PR12167 { + template<int N> struct string {}; + + struct X { + X(const char v); + template<typename T> bool operator()(T) const; + }; + + template<int N, class Comparator> bool g(const string<N>& s, Comparator cmp) { + return cmp(s); + } + template<int N> bool f(const string<N> &s) { + return g(s, X{'x'}); + } + + bool s = f(string<1>()); +} + +namespace PR12257_PR12241 { + struct command_pair + { + command_pair(int, int); + }; + + struct command_map + { + command_map(std::initializer_list<command_pair>); + }; + + struct generator_pair + { + generator_pair(const command_map); + }; + + // 5 levels: init list, gen_pair, command_map, init list, command_pair + const std::initializer_list<generator_pair> x = {{{{{3, 4}}}}}; + + // 4 levels: init list, gen_pair, command_map via init list, command_pair + const std::initializer_list<generator_pair> y = {{{{1, 2}}}}; +} + +namespace PR12120 { + struct A { explicit A(int); A(float); }; // expected-note {{declared here}} + A a = { 0 }; // expected-error {{constructor is explicit}} + + struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}} + B b = { 0 }; // expected-error {{ambiguous}} +} + +namespace PR12498 { + class ArrayRef; // expected-note{{forward declaration}} + + struct C { + void foo(const ArrayRef&); // expected-note{{passing argument to parameter here}} + }; + + static void bar(C* c) + { + c->foo({ nullptr, 1 }); // expected-error{{initialization of incomplete type 'const PR12498::ArrayRef'}} + } + +} diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp new file mode 100644 index 0000000..d8fdd5a --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-references.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct one { char c; }; +struct two { char c[2]; }; + +namespace reference { + struct A { + int i1, i2; + }; + + void single_init() { + const int &cri1a = {1}; + const int &cri1b{1}; + + int i = 1; + int &ri1a = {i}; + int &ri1b{i}; + + int &ri2 = {1}; // expected-error {{cannot bind to an initializer list temporary}} + + A a{1, 2}; + A &ra1a = {a}; + A &ra1b{a}; + } + + void reference_to_aggregate() { + const A &ra1{1, 2}; + A &ra2{1, 2}; // expected-error {{cannot bind to an initializer list temporary}} + + const int (&arrayRef)[] = {1, 2, 3}; + static_assert(sizeof(arrayRef) == 3 * sizeof(int), "bad array size"); + } + + struct B { + int i1; + }; + + void call() { + void f(const int&); + f({1}); + + void g(int&); // expected-note {{passing argument}} + g({1}); // expected-error {{cannot bind to an initializer list temporary}} + int i = 0; + g({i}); + + void h(const B&); + h({1}); + + void a(B&); // expected-note {{passing argument}} + a({1}); // expected-error {{cannot bind to an initializer list temporary}} + B b{1}; + a({b}); + } + + void overloading() { + one f(const int&); + two f(const B&); + + // First is identity conversion, second is user-defined conversion. + static_assert(sizeof(f({1})) == sizeof(one), "bad overload resolution"); + + one g(int&); + two g(const B&); + + static_assert(sizeof(g({1})) == sizeof(two), "bad overload resolution"); + + one h(const int&); + two h(const A&); + + static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution"); + } + + void edge_cases() { + // FIXME: very poor error message + int const &b({0}); // expected-error {{could not bind}} + } + +} + +namespace PR12182 { + void f(int const(&)[3]); + + void g() { + f({1, 2}); + } +} diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp index 41fc219..627855e 100644 --- a/test/SemaCXX/cxx0x-initializer-scalars.cpp +++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -1,5 +1,40 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +struct one { char c[1]; }; +struct two { char c[2]; }; + +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() { @@ -12,6 +47,8 @@ namespace integral { // FIXME: Redundant warnings. { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}} + { if (const int a{1}) static_assert(a == 1, ""); } + { if (const int a = {1}) static_assert(a == 1, ""); } } int direct_usage() { @@ -22,7 +59,7 @@ namespace integral { } void inline_init() { - (void) int{1}; + auto v = int{1}; (void) new int{1}; } @@ -31,4 +68,49 @@ namespace integral { A() : i{1} {} }; + void function_call() { + void takes_int(int); + takes_int({1}); + } + + void overloaded_call() { + one overloaded(int); + two overloaded(double); + + static_assert(sizeof(overloaded({0})) == sizeof(one), "bad overload"); + static_assert(sizeof(overloaded({0.0})) == sizeof(two), "bad overload"); + + void ambiguous(int, double); // expected-note {{candidate}} + void ambiguous(double, int); // expected-note {{candidate}} + ambiguous({0}, {0}); // expected-error {{ambiguous}} + + void emptylist(int); + void emptylist(int, int, int); + emptylist({}); + emptylist({}, {}, {}); + } + + void edge_cases() { + // FIXME: very poor error message + int a({0}); // expected-error {{cannot initialize}} + (void) int({0}); // expected-error {{functional-style cast}} + new int({0}); // expected-error {{cannot initialize}} + } + + void default_argument(int i = {}) { + } + struct DefaultArgument { + void default_argument(int i = {}) { + } + }; +} + +namespace PR12118 { + void test() { + one f(std::initializer_list<int>); + two f(int); + + // to initializer_list is preferred + static_assert(sizeof(f({0})) == sizeof(one), "bad overload"); + } } diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp new file mode 100644 index 0000000..7384309 --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -0,0 +1,177 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// This must obviously come before the definition of std::initializer_list. +void missing_initializerlist() { + auto l = {1, 2, 3, 4}; // expected-error {{std::initializer_list was not found}} +} + +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_;} + }; +} + +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; }; + +struct one { char c[1]; }; +struct two { char c[2]; }; + +struct A { + int a, b; +}; + +struct B { + B(); + B(int, int); +}; + +void simple_list() { + std::initializer_list<int> il = { 1, 2, 3 }; + std::initializer_list<double> dl = { 1.0, 2.0, 3 }; + std::initializer_list<A> al = { {1, 2}, {2, 3}, {3, 4} }; + std::initializer_list<B> bl = { {1, 2}, {2, 3}, {} }; +} + +void function_call() { + void f(std::initializer_list<int>); + f({1, 2, 3}); + + void g(std::initializer_list<B>); + g({ {1, 2}, {2, 3}, {} }); +} + +struct C { + C(int); +}; + +struct D { + D(); + operator int(); + operator C(); +}; + +void overloaded_call() { + one overloaded(std::initializer_list<int>); + two overloaded(std::initializer_list<B>); + + static_assert(sizeof(overloaded({1, 2, 3})) == sizeof(one), "bad overload"); + static_assert(sizeof(overloaded({ {1, 2}, {2, 3}, {} })) == sizeof(two), "bad overload"); + + void ambiguous(std::initializer_list<A>); // expected-note {{candidate}} + void ambiguous(std::initializer_list<B>); // expected-note {{candidate}} + ambiguous({ {1, 2}, {2, 3}, {3, 4} }); // expected-error {{ambiguous}} + + one ov2(std::initializer_list<int>); // expected-note {{candidate}} + two ov2(std::initializer_list<C>); // expected-note {{candidate}} + // Worst sequence to int is identity, whereas to C it's user-defined. + static_assert(sizeof(ov2({1, 2, 3})) == sizeof(one), "bad overload"); + // But here, user-defined is worst in both cases. + ov2({1, 2, D()}); // expected-error {{ambiguous}} +} + +template <typename T> +T deduce(std::initializer_list<T>); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}} +template <typename T> +T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}} + +void argument_deduction() { + static_assert(same_type<decltype(deduce({1, 2, 3})), int>::value, "bad deduction"); + static_assert(same_type<decltype(deduce({1.0, 2.0, 3.0})), double>::value, "bad deduction"); + + deduce({1, 2.0}); // expected-error {{no matching function}} + + static_assert(same_type<decltype(deduce_ref({1, 2, 3})), int>::value, "bad deduction"); + static_assert(same_type<decltype(deduce_ref({1.0, 2.0, 3.0})), double>::value, "bad deduction"); + + deduce_ref({1, 2.0}); // expected-error {{no matching function}} +} + +void auto_deduction() { + 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}) {} +} + +void dangle() { + new auto{1, 2, 3}; // expected-error {{cannot use list-initialization}} + new std::initializer_list<int>{1, 2, 3}; // expected-warning {{at the end of the full-expression}} +} + +struct haslist1 { + std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the end of the constructor}} + std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end of the constructor}} + haslist1(); +}; + +haslist1::haslist1() +: il{1, 2, 3} // expected-warning{{at the end of the constructor}} +{} + +namespace PR12119 { + // Deduction with nested initializer lists. + template<typename T> void f(std::initializer_list<T>); + template<typename T> void g(std::initializer_list<std::initializer_list<T>>); + + void foo() { + f({0, {1}}); + g({{0, 1}, {2, 3}}); + std::initializer_list<int> il = {1, 2}; + g({il, {2, 3}}); + } +} + +namespace Decay { + template<typename T> + void f(std::initializer_list<T>) { + T x = 1; // expected-error{{cannot initialize a variable of type 'const char *' with an rvalue of type 'int'}} + } + + void g() { + f({"A", "BB", "CCC"}); // expected-note{{in instantiation of function template specialization 'Decay::f<const char *>' requested here}} + + auto x = { "A", "BB", "CCC" }; + std::initializer_list<const char *> *il = &x; + + for( auto s : {"A", "BB", "CCC", "DDD"}) { } + } +} + +namespace PR12436 { + struct X { + template<typename T> + X(std::initializer_list<int>, T); + }; + + X x({}, 17); +} diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp index 6275af6..0e4add8 100644 --- a/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -10,9 +10,20 @@ struct non_trivial { union u { non_trivial nt; }; +union u2 { + non_trivial nt; + int k; + u2(int k) : k(k) {} + u2() : nt() {} +}; + +union static_data_member { + static int i; +}; +int static_data_member::i; union bad { - static int i; // expected-error {{static data member}} + int &i; // expected-error {{union member 'i' has reference type 'int &'}} }; struct s { @@ -20,3 +31,94 @@ struct s { non_trivial nt; }; }; + +// Don't crash on this. +struct TemplateCtor { template<typename T> TemplateCtor(T); }; +union TemplateCtorMember { TemplateCtor s; }; + +template<typename T> struct remove_ref { typedef T type; }; +template<typename T> struct remove_ref<T&> { typedef T type; }; +template<typename T> struct remove_ref<T&&> { typedef T type; }; +template<typename T> T &&forward(typename remove_ref<T>::type &&t); +template<typename T> T &&forward(typename remove_ref<T>::type &t); +template<typename T> typename remove_ref<T>::type &&move(T &&t); + +using size_t = decltype(sizeof(int)); +void *operator new(size_t, void *p) noexcept { return p; } + +namespace disabled_dtor { + template<typename T> + union disable_dtor { + T val; + template<typename...U> + disable_dtor(U &&...u) : val(forward<U>(u)...) {} + ~disable_dtor() {} + }; + + struct deleted_dtor { + deleted_dtor(int n, char c) : n(n), c(c) {} + int n; + char c; + ~deleted_dtor() = delete; + }; + + disable_dtor<deleted_dtor> dd(4, 'x'); +} + +namespace optional { + template<typename T> struct optional { + bool has; + union { T value; }; + + optional() : has(false) {} + template<typename...U> + optional(U &&...u) : has(true), value(forward<U>(u)...) {} + + optional(const optional &o) : has(o.has) { + if (has) new (&value) T(o.value); + } + optional(optional &&o) : has(o.has) { + if (has) new (&value) T(move(o.value)); + } + + optional &operator=(const optional &o) { + if (has) { + if (o.has) + value = o.value; + else + value.~T(); + } else if (o.has) { + new (&value) T(o.value); + } + has = o.has; + } + optional &operator=(optional &&o) { + if (has) { + if (o.has) + value = move(o.value); + else + value.~T(); + } else if (o.has) { + new (&value) T(move(o.value)); + } + has = o.has; + } + + ~optional() { + if (has) + value.~T(); + } + + explicit operator bool() const { return has; } + T &operator*() const { return value; } + }; + + optional<non_trivial> o1; + optional<non_trivial> o2{non_trivial()}; + optional<non_trivial> o3{*o2}; + void f() { + if (o2) + o1 = o2; + o2 = optional<non_trivial>(); + } +} diff --git a/test/SemaCXX/cxx0x-return-init-list.cpp b/test/SemaCXX/cxx0x-return-init-list.cpp index b786922..da83271 100644 --- a/test/SemaCXX/cxx0x-return-init-list.cpp +++ b/test/SemaCXX/cxx0x-return-init-list.cpp @@ -1,17 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// This test checks for a teeny tiny subset of the functionality in -// the C++11 generalized initializer lists feature, which happens to -// be used in libstdc++ 4.5. We accept only this syntax so that Clang -// can handle the libstdc++ 4.5 headers. +// Test that a very basic variation of generalized initializer returns (that +// required for libstdc++ 4.5) is supported in C++98. int test0(int i) { - return { i }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}} + return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}} } template<typename T, typename U> T test1(U u) { - return { u }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}} + return { u }; // expected-warning{{generalized initializer lists are a C++11 extension}} } template int test1(char); diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp new file mode 100644 index 0000000..afabf88 --- /dev/null +++ b/test/SemaCXX/cxx11-ast-print.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++11 -ast-print %s | FileCheck %s + +// FIXME: Print the trailing-return-type properly. +// CHECK: decltype(nullptr) operator "" _foo(const char *p, decltype(sizeof(int))); +auto operator"" _foo(const char *p, decltype(sizeof(int))) -> decltype(nullptr); + +// CHECK: decltype(""_foo) operator "" _bar(unsigned long long); +decltype(""_foo) operator"" _bar(unsigned long long); + +// CHECK: decltype(42_bar) operator "" _baz(long double); +decltype(42_bar) operator"" _baz(long double); + +// CHECK: decltype(4.5_baz) operator "" _baz(char); +decltype(4.5_baz) operator"" _baz(char); + +// CHECK: const char *operator "" _quux(const char *); +const char *operator"" _quux(const char *); + +// CHECK: template <char...> const char *operator "" _fritz(); +template<char...> const char *operator"" _fritz(); + +// CHECK: const char *p1 = "bar1"_foo; +const char *p1 = "bar1"_foo; +// CHECK: const char *p2 = "bar2"_foo; +const char *p2 = R"x(bar2)x"_foo; +// CHECK: const char *p3 = u8"bar3"_foo; +const char *p3 = u8"bar3"_foo; +// CHECK: const char *p4 = 297_bar; +const char *p4 = 0x129_bar; +// CHECK: const char *p5 = 1.0E+12_baz; +const char *p5 = 1e12_baz; +// CHECK: const char *p6 = 'x'_baz; +const char *p6 = 'x'_baz; +// CHECK: const char *p7 = 123_quux; +const char *p7 = 123_quux; +// CHECK: const char *p8 = 4.9_quux; +const char *p8 = 4.9_quux; +// CHECK: const char *p9 = 0x42e3F_fritz; +const char *p9 = 0x42e3F_fritz; +// CHECK: const char *p10 = 3.300e+15_fritz; +const char *p10 = 3.300e+15_fritz; diff --git a/test/SemaCXX/cxx11-user-defined-literals.cpp b/test/SemaCXX/cxx11-user-defined-literals.cpp new file mode 100644 index 0000000..4bbecdb --- /dev/null +++ b/test/SemaCXX/cxx11-user-defined-literals.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -fms-extensions -triple x86_64-apple-darwin9.0.0 + +using size_t = decltype(sizeof(int)); +enum class LitKind { + Char, WideChar, Char16, Char32, + CharStr, WideStr, Char16Str, Char32Str, + Integer, Floating, Raw, Template +}; +constexpr LitKind operator"" _kind(char p) { return LitKind::Char; } +constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; } +constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; } +constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; } +constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; } +constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; } +constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; } +constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; } +constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; } +constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; } +constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; } +template<char ...Cs> constexpr LitKind operator"" _kind3() { return LitKind::Template; } + +static_assert('x'_kind == LitKind::Char, ""); +static_assert(L'x'_kind == LitKind::WideChar, ""); +static_assert(u'x'_kind == LitKind::Char16, ""); +static_assert(U'x'_kind == LitKind::Char32, ""); +static_assert("foo"_kind == LitKind::CharStr, ""); +static_assert(u8"foo"_kind == LitKind::CharStr, ""); +static_assert(L"foo"_kind == LitKind::WideStr, ""); +static_assert(u"foo"_kind == LitKind::Char16Str, ""); +static_assert(U"foo"_kind == LitKind::Char32Str, ""); +static_assert(194_kind == LitKind::Integer, ""); +static_assert(0377_kind == LitKind::Integer, ""); +static_assert(0x5ffc_kind == LitKind::Integer, ""); +static_assert(.5954_kind == LitKind::Floating, ""); +static_assert(1._kind == LitKind::Floating, ""); +static_assert(1.e-2_kind == LitKind::Floating, ""); +static_assert(4e6_kind == LitKind::Floating, ""); +static_assert(4e6_kind2 == LitKind::Raw, ""); +static_assert(4e6_kind3 == LitKind::Template, ""); + +constexpr const char *fractional_digits_impl(const char *p) { + return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0; +} +constexpr const char *operator"" _fractional_digits(const char *p) { + return fractional_digits_impl(p) ?: p; +} +constexpr bool streq(const char *p, const char *q) { + return *p == *q && (!*p || streq(p+1, q+1)); +} + +static_assert(streq(143.97_fractional_digits, "97"), ""); +static_assert(streq(0x786_fractional_digits, "0x786"), ""); +static_assert(streq(.4_fractional_digits, "4"), ""); +static_assert(streq(4._fractional_digits, ""), ""); +static_assert(streq(1e+97_fractional_digits, "1e+97"), ""); +static_assert(streq(0377_fractional_digits, "0377"), ""); +static_assert(streq(0377.5_fractional_digits, "5"), ""); + +int operator"" _ambiguous(char); // expected-note {{candidate}} +namespace N { + void *operator"" _ambiguous(char); // expected-note {{candidate}} +} +using namespace N; +int k = 'x'_ambiguous; // expected-error {{ambiguous}} + +int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}} +int m = 42_deleted; // expected-error {{attempt to use a deleted}} + +namespace Using { + namespace M { + int operator"" _using(char); + } + int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator "" _using'}} + + using M::operator "" _using; + int k2 = 'x'_using; +} + +namespace AmbiguousRawTemplate { + int operator"" _ambig1(const char *); // expected-note {{candidate}} + template<char...> int operator"" _ambig1(); // expected-note {{candidate}} + + int k1 = 123_ambig1; // expected-error {{call to 'operator "" _ambig1' is ambiguous}} + + namespace Inner { + template<char...> int operator"" _ambig2(); // expected-note 3{{candidate}} + } + int operator"" _ambig2(const char *); // expected-note 3{{candidate}} + using Inner::operator"" _ambig2; + + int k2 = 123_ambig2; // expected-error {{call to 'operator "" _ambig2' is ambiguous}} + + namespace N { + using Inner::operator"" _ambig2; + + int k3 = 123_ambig2; // ok + + using AmbiguousRawTemplate::operator"" _ambig2; + + int k4 = 123_ambig2; // expected-error {{ambiguous}} + + namespace M { + + template<char...> int operator"" _ambig2(); + + int k5 = 123_ambig2; // ok + } + + int operator"" _ambig2(unsigned long long); + + int k6 = 123_ambig2; // ok + int k7 = 123._ambig2; // expected-error {{ambiguous}} + } +} + +constexpr unsigned mash(unsigned a) { + return 0x93ae27b5 * ((a >> 13) | a << 19); +} +template<typename=void> constexpr unsigned hash(unsigned a) { return a; } +template<char C, char...Cs> constexpr unsigned hash(unsigned a) { + return hash<Cs...>(mash(a ^ mash(C))); +} +template<typename T, T v> struct constant { constexpr static T value = v; }; +template<char...Cs> constexpr unsigned operator"" _hash() { + return constant<unsigned, hash<Cs...>(0)>::value; +} +static_assert(0x1234_hash == 0x103eff5e, ""); +static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, ""); + +// Functions and literal suffixes go in separate namespaces. +namespace Namespace { + template<char...> int operator"" _x(); + int k = _x(); // expected-error {{undeclared identifier '_x'}} + + int _y(unsigned long long); + int k2 = 123_y; // expected-error {{no matching literal operator for call to 'operator "" _y'}} +} diff --git a/test/SemaCXX/cxx98-compat-flags.cpp b/test/SemaCXX/cxx98-compat-flags.cpp new file mode 100644 index 0000000..6dc24be --- /dev/null +++ b/test/SemaCXX/cxx98-compat-flags.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Wno-bind-to-temporary-copy -Wno-unnamed-type-template-args -Wno-local-type-template-args -Werror %s + +template<typename T> int TemplateFn(T) { return 0; } +void LocalTemplateArg() { + struct S {}; + TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}} +} +struct {} obj_of_unnamed_type; // expected-note {{here}} +int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}} + +namespace CopyCtorIssues { + struct Private { + Private(); + private: + Private(const Private&); // expected-note {{declared private here}} + }; + struct NoViable { + NoViable(); + NoViable(NoViable&); // expected-note {{not viable}} + }; + struct Ambiguous { + Ambiguous(); + Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}} + Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}} + }; + struct Deleted { + Private p; // expected-note {{copy constructor of 'Deleted' is implicitly deleted because field 'p' has an inaccessible copy constructor}} + }; + + const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}} + const NoViable &b = NoViable(); // expected-warning {{copying variable of type 'CopyCtorIssues::NoViable' when binding a reference to a temporary would find no viable constructor in C++98}} + const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}} + const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}} +} diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp index 2ca0ae4..00532d5 100644 --- a/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat-pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -Werror %s // RUN: %clang_cc1 -fsyntax-only -std=c++98 -Werror %s // -Wc++98-compat-pedantic warns on C++11 features which we accept without a @@ -9,3 +10,25 @@ #define VA_MACRO(x, ...) x // expected-warning {{variadic macros are incompatible with C++98}} VA_MACRO(,x) // expected-warning {{empty macro argument list is incompatible with C++98}} + +; // expected-warning {{extra ';' outside of a function is incompatible with C++98}} + +enum Enum { + Enum_value, // expected-warning {{commas at the end of enumerator lists are incompatible with C++98}} +}; + +template<typename T> struct InstantiationAfterSpecialization {}; +template<> struct InstantiationAfterSpecialization<int> {}; // expected-note {{here}} +template struct InstantiationAfterSpecialization<int>; // expected-warning {{explicit instantiation of 'InstantiationAfterSpecialization<int>' that occurs after an explicit specialization is incompatible with C++98}} + +void *dlsym(); +void (*FnPtr)() = (void(*)())dlsym(); // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}} +void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}} + +struct ConvertToInt { + operator int(); +}; +int *ArraySizeConversion = new int[ConvertToInt()]; // expected-warning {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}} + +template<typename T> class ExternTemplate {}; +extern template class ExternTemplate<int>; // expected-warning {{extern templates are incompatible with C++98}} diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 6a3881c..4758913 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s + +namespace std { struct type_info; } template<typename ...T> // expected-warning {{variadic templates are incompatible with C++98}} class Variadic1 {}; @@ -27,4 +30,272 @@ void Literals() { } template<typename T> struct S {}; -S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}} +namespace TemplateParsing { + S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}} + S< ::S<void>> t; // expected-warning {{consecutive right angle brackets are incompatible with C++98 (use '> >')}} +} + +void Lambda() { + []{}(); // expected-warning {{lambda expressions are incompatible with C++98}} +} + +int InitList(int i = {}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} \ + // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} + (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ + // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} + (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ + // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} + int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} + S<int> s = {}; // ok, aggregate + s = {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} + return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} +} +struct DelayedDefaultArgumentParseInitList { + void f(int i = {1}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} + } +}; + +int operator"" _hello(const char *); // expected-warning {{literal operators are incompatible with C++98}} + +enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}} +}; + +enum class EnumScoped { // expected-warning {{scoped enumerations are incompatible with C++98}} +}; + +void Deleted() = delete; // expected-warning {{deleted function definitions are incompatible with C++98}} +struct Defaulted { + Defaulted() = default; // expected-warning {{defaulted function definitions are incompatible with C++98}} +}; + +int &&RvalueReference = 0; // expected-warning {{rvalue references are incompatible with C++98}} +struct RefQualifier { + void f() &; // expected-warning {{reference qualifiers on functions are incompatible with C++98}} +}; + +auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}} + +void RangeFor() { + int xs[] = {1, 2, 3}; + for (int &a : xs) { // expected-warning {{range-based for loop is incompatible with C++98}} + } +} + +struct InClassInit { + int n = 0; // expected-warning {{in-class initialization of non-static data members is incompatible with C++98}} +}; + +struct OverrideControlBase { + virtual void f(); + virtual void g(); +}; +struct OverrideControl final : OverrideControlBase { // expected-warning {{'final' keyword is incompatible with C++98}} + virtual void f() override; // expected-warning {{'override' keyword is incompatible with C++98}} + virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}} +}; + +using AliasDecl = int; // expected-warning {{alias declarations are incompatible with C++98}} +template<typename T> using AliasTemplate = T; // expected-warning {{alias declarations are incompatible with C++98}} + +inline namespace InlineNS { // expected-warning {{inline namespaces are incompatible with C++98}} +} + +auto auto_deduction = 0; // expected-warning {{'auto' type specifier is incompatible with C++98}} +int *p = new auto(0); // expected-warning {{'auto' type specifier is incompatible with C++98}} + +const int align_of = alignof(int); // expected-warning {{alignof expressions are incompatible with C++98}} +char16_t c16 = 0; // expected-warning {{'char16_t' type specifier is incompatible with C++98}} +char32_t c32 = 0; // expected-warning {{'char32_t' type specifier is incompatible with C++98}} +constexpr int const_expr = 0; // expected-warning {{'constexpr' specifier is incompatible with C++98}} +decltype(const_expr) decl_type = 0; // expected-warning {{'decltype' type specifier is incompatible with C++98}} +__decltype(const_expr) decl_type2 = 0; // ok +void no_except() noexcept; // expected-warning {{noexcept specifications are incompatible with C++98}} +bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expressions are incompatible with C++98}} +void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}} +static_assert(true, "!"); // expected-warning {{static_assert declarations are incompatible with C++98}} + +struct InhCtorBase { + InhCtorBase(int); +}; +struct InhCtorDerived : InhCtorBase { + using InhCtorBase::InhCtorBase; // expected-warning {{inherited constructors are incompatible with C++98}} +}; + +struct FriendMember { + static void MemberFn(); + friend void FriendMember::MemberFn(); // expected-warning {{friend declaration naming a member of the declaring class is incompatible with C++98}} +}; + +struct DelegCtor { + DelegCtor(int) : DelegCtor() {} // expected-warning {{delegating constructors are incompatible with C++98}} + DelegCtor(); +}; + +template<int n = 0> void DefaultFuncTemplateArg(); // expected-warning {{default template arguments for a function template are incompatible with C++98}} + +template<typename T> int TemplateFn(T) { return 0; } +void LocalTemplateArg() { + struct S {}; + TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}} +} +struct {} obj_of_unnamed_type; // expected-note {{here}} +int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}} + +namespace RedundantParensInAddressTemplateParam { + int n; + template<int*p> struct S {}; + S<(&n)> s; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}} + S<(((&n)))> t; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}} +} + +namespace TemplateSpecOutOfScopeNs { + template<typename T> struct S {}; // expected-note {{here}} +} +template<> struct TemplateSpecOutOfScopeNs::S<char> {}; // expected-warning {{class template specialization of 'S' outside namespace 'TemplateSpecOutOfScopeNs' is incompatible with C++98}} + +struct Typename { + template<typename T> struct Inner {}; +}; +typename ::Typename TypenameOutsideTemplate(); // expected-warning {{use of 'typename' outside of a template is incompatible with C++98}} +Typename::template Inner<int> TemplateOutsideTemplate(); // expected-warning {{use of 'template' keyword outside of a template is incompatible with C++98}} + +struct TrivialButNonPOD { + int f(int); +private: + int k; +}; +void Ellipsis(int n, ...); +void TrivialButNonPODThroughEllipsis() { + Ellipsis(1, TrivialButNonPOD()); // expected-warning {{passing object of trivial but non-POD type 'TrivialButNonPOD' through variadic function is incompatible with C++98}} +} + +struct HasExplicitConversion { + explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}} +}; + +struct Struct {}; +enum Enum { enum_val = 0 }; +struct BadFriends { + friend enum ::Enum; // expected-warning {{befriending enumeration type 'enum ::Enum' is incompatible with C++98}} + friend int; // expected-warning {{non-class friend type 'int' is incompatible with C++98}} + friend Struct; // expected-warning {{befriending 'Struct' without 'struct' keyword is incompatible with C++98}} +}; + +int n = {}; // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} + +class PrivateMember { + struct ImPrivate {}; +}; +template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}} + return typename T::ImPrivate(); +} +int SFINAEAccessControl(...) { return 0; } +int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember()); + +template<typename T> +struct FriendRedefinition { + friend void Friend() {} // expected-warning {{friend function 'Friend' would be implicitly redefined in C++98}} expected-note {{previous}} +}; +FriendRedefinition<int> FriendRedef1; +FriendRedefinition<char> FriendRedef2; // expected-note {{requested here}} + +namespace CopyCtorIssues { + struct Private { + Private(); + private: + Private(const Private&); // expected-note {{declared private here}} + }; + struct NoViable { + NoViable(); + NoViable(NoViable&); // expected-note {{not viable}} + }; + struct Ambiguous { + Ambiguous(); + Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}} + Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}} + }; + struct Deleted { + Private p; // expected-note {{implicitly deleted}} + }; + + const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}} + const NoViable &b = NoViable(); // expected-warning {{copying variable of type 'CopyCtorIssues::NoViable' when binding a reference to a temporary would find no viable constructor in C++98}} + const Ambiguous &c = Ambiguous(); // expected-warning {{copying variable of type 'CopyCtorIssues::Ambiguous' when binding a reference to a temporary would find ambiguous constructors in C++98}} + const Deleted &d = Deleted(); // expected-warning {{copying variable of type 'CopyCtorIssues::Deleted' when binding a reference to a temporary would invoke a deleted constructor in C++98}} +} + +namespace UnionOrAnonStructMembers { + struct NonTrivCtor { + NonTrivCtor(); // expected-note 2{{user-declared constructor}} + }; + struct NonTrivCopy { + NonTrivCopy(const NonTrivCopy&); // expected-note 2{{user-declared copy constructor}} + }; + struct NonTrivDtor { + ~NonTrivDtor(); // expected-note 2{{user-declared destructor}} + }; + union BadUnion { + NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial constructor is incompatible with C++98}} + NonTrivCopy ntcp; // expected-warning {{union member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} + NonTrivDtor ntd; // expected-warning {{union member 'ntd' with a non-trivial destructor is incompatible with C++98}} + }; + struct Wrap { + struct { + NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial constructor is incompatible with C++98}} + NonTrivCopy ntcp; // expected-warning {{anonymous struct member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} + NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}} + }; + }; + union WithStaticDataMember { + static constexpr double d = 0.0; // expected-warning {{static data member 'd' in union is incompatible with C++98}} expected-warning {{'constexpr' specifier is incompatible with C++98}} + static const int n = 0; // expected-warning {{static data member 'n' in union is incompatible with C++98}} + static int k; // expected-warning {{static data member 'k' in union is incompatible with C++98}} + }; +} + +int EnumNNS = Enum::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}} +template<typename T> void EnumNNSFn() { + int k = T::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}} +}; +template void EnumNNSFn<Enum>(); // expected-note {{in instantiation}} + +void JumpDiagnostics(int n) { + goto DirectJump; // expected-warning {{goto would jump into protected scope in C++98}} + TrivialButNonPOD tnp1; // expected-note {{jump bypasses initialization of non-POD variable}} + +DirectJump: + void *Table[] = {&&DirectJump, &&Later}; + goto *Table[n]; // expected-warning {{indirect goto might cross protected scopes in C++98}} + + TrivialButNonPOD tnp2; // expected-note {{jump bypasses initialization of non-POD variable}} +Later: // expected-note {{possible target of indirect goto}} + switch (n) { + TrivialButNonPOD tnp3; // expected-note {{jump bypasses initialization of non-POD variable}} + default: // expected-warning {{switch case would be in a protected scope in C++98}} + return; + } +} + +namespace UnevaluatedMemberAccess { + struct S { + int n; + int f() { return sizeof(S::n); } // ok + }; + int k = sizeof(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} + const std::type_info &ti = typeid(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} +} + +namespace LiteralUCNs { + char c1 = '\u001e'; // expected-warning {{universal character name referring to a control character is incompatible with C++98}} + wchar_t c2 = L'\u0041'; // expected-warning {{specifying character 'A' with a universal character name is incompatible with C++98}} + const char *s1 = "foo\u0031"; // expected-warning {{specifying character '1' with a universal character name is incompatible with C++98}} + const wchar_t *s2 = L"bar\u0085"; // expected-warning {{universal character name referring to a control character is incompatible with C++98}} +} + +namespace NonTypeTemplateArgs { + template<typename T, T v> struct S {}; + const int k = 5; // expected-note {{here}} + static void f() {} // expected-note {{here}} + S<const int&, k> s1; // expected-warning {{non-type template argument referring to object 'k' with internal linkage is incompatible with C++98}} + S<void(&)(), f> s2; // expected-warning {{non-type template argument referring to function 'f' with internal linkage is incompatible with C++98}} +} diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp index 2dbd381..bd3de9e 100644 --- a/test/SemaCXX/dcl_init_aggr.cpp +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -80,7 +80,7 @@ struct HasReference { }; int global_int; HasReference r1 = { 1, global_int }; -HasReference r2 = { 1 } ; // expected-error{{initialization leaves reference member of type 'int &' uninitialized}} +HasReference r2 = { 1 } ; // expected-error{{reference member of type 'int &' uninitialized}} // C++ [dcl.init.aggr]p10 // Note: the behavior here is identical to C diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 1ddff80..6f4d08c 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -pedantic-errors %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic-errors %s void f() { int a; @@ -24,14 +24,43 @@ void f() { // 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}} + typedef T(*td)(int(p)); + extern T(*tp)(int(p)); + T d3(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} + T d3v(void); + typedef T d3t(); + extern T f3(); + __typeof(*T()) f4(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} + typedef void *V; + __typeof(*V()) f5(); + T multi1, + multi2(); // expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} T(d)[5]; // expected-error {{redefinition of 'd'}} typeof(int[])(f) = { 1, 2 }; // expected-error {{extension used}} void(b)(int); - int(d2) __attribute__(()); + int(d2) __attribute__(()); if (int(a)=1) {} int(d3(int())); } +struct RAII { + RAII(); + ~RAII(); +}; + +void func(); +namespace N { + struct S; + + void emptyParens() { + RAII raii(); // expected-warning {{function declaration}} expected-note {{remove parentheses to declare a variable}} + int a, b, c, d, e, // expected-note {{change this ',' to a ';' to call 'func'}} + func(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}} + + S s(); // expected-warning {{function declaration}} + } +} + class C { }; void fn(int(C)) { } // void fn(int(*fp)(C c)) { } expected-note{{candidate function}} // not: void fn(int C); diff --git a/test/SemaCXX/decltype-crash.cpp b/test/SemaCXX/decltype-crash.cpp index 50b3e49..002bd4c 100644 --- a/test/SemaCXX/decltype-crash.cpp +++ b/test/SemaCXX/decltype-crash.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s int& a(); diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp index 78fb8ef..a1200e0 100644 --- a/test/SemaCXX/decltype.cpp +++ b/test/SemaCXX/decltype.cpp @@ -20,4 +20,11 @@ namespace pr10154 { class A{ A(decltype(nullptr) param); }; -}
\ No newline at end of file +} + +template<typename T> struct S {}; +template<typename T> auto f(T t) -> decltype(S<int>(t)) { + using U = decltype(S<int>(t)); + using U = S<int>; + return S<int>(t); +} diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp index e9d8a2f..ae6ef97 100644 --- a/test/SemaCXX/default1.cpp +++ b/test/SemaCXX/default1.cpp @@ -32,3 +32,21 @@ void k(Y y = 17); // expected-error{{no viable conversion}} \ void kk(Y = 17); // expected-error{{no viable conversion}} \ // expected-note{{passing argument to parameter here}} + +int l () { + int m(int i, int j, int k = 3); + if (1) + { + int m(int i, int j = 2, int k = 4); + m(8); + } + return 0; +} + +int i () { + void j (int f = 4); + { + void j (int f); // expected-note{{'j' declared here}} + j(); // expected-error{{too few arguments to function call, expected 1, have 0}} + } +} diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp index 2076322..1626044 100644 --- a/test/SemaCXX/default2.cpp +++ b/test/SemaCXX/default2.cpp @@ -28,7 +28,7 @@ void g(int x, int y = x); // expected-error {{default argument references parame void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}} class X { - void f(X* x = this); // expected-error{{invalid use of 'this' outside of a nonstatic member function}} + void f(X* x = this); // expected-error{{invalid use of 'this' outside of a non-static member function}} void g() { int f(X* x = this); // expected-error{{default argument references 'this'}} @@ -55,7 +55,7 @@ void C::h() { // C++ [dcl.fct.default]p9 struct Y { int a; - int mem1(int i = a); // expected-error{{invalid use of nonstatic data member 'a'}} + int mem1(int i = a); // expected-error{{invalid use of non-static data member 'a'}} int mem2(int i = b); // OK; use Y::b int mem3(int i); int mem4(int i); @@ -64,8 +64,8 @@ struct Y { 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 l = a, // expected-error{{invalid use of non-static data member 'a'}} + Nested* self = this, // expected-error{{invalid use of 'this' outside of a non-static member function}} int m); // expected-error{{missing default argument on parameter 'm'}} static int c; Nested(int i = 42); @@ -78,7 +78,7 @@ struct Y { 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'}} +int Y::mem4(int i = a) // expected-error{{invalid use of non-static data member 'a'}} { return i; } diff --git a/test/SemaCXX/defaulted-private-dtor.cpp b/test/SemaCXX/defaulted-private-dtor.cpp new file mode 100644 index 0000000..e6f9555 --- /dev/null +++ b/test/SemaCXX/defaulted-private-dtor.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s -fcxx-exceptions + +class BadDtor { + // A private, but nonetheless trivial, destructor. + ~BadDtor() = default; // expected-note 9{{here}} + friend class K; +}; +void f() { + BadDtor *p = new BadDtor[3]; // expected-error {{private destructor}} + delete [] p; // expected-error {{private destructor}} + const BadDtor &dd2 = BadDtor(); // expected-error {{private destructor}} + BadDtor dd; // expected-error {{private destructor}} + throw dd; // expected-error {{private destructor}} +} +struct V { + V(); + BadDtor bd; // expected-note {{inaccessible destructor}} +}; +V v; // expected-error {{deleted function}} +struct W : BadDtor { // expected-note {{inaccessible destructor}} + W(); +}; +W w; // expected-error {{deleted function}} +struct X : BadDtor { // expected-error {{private destructor}} + ~X() {} +}; +struct Y { + BadDtor dd; // expected-error {{private destructor}} + ~Y() {} +}; +struct Z : virtual BadDtor { // expected-error {{private destructor}} + ~Z() {} +}; +BadDtor dd; // expected-error {{private destructor}} + +class K : BadDtor { + void f() { + BadDtor *p = new BadDtor[3]; + delete [] p; + const BadDtor &dd2 = BadDtor(); + BadDtor dd; + throw dd; + + { + BadDtor x; + goto dont_call_dtor; + } +dont_call_dtor: + ; + } + struct Z : virtual BadDtor { + ~Z() {} + }; + BadDtor dd; + ~K(); +}; diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index 4620a19..d13fd0e 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s int i = delete; // expected-error {{only functions can have deleted definitions}} @@ -33,3 +33,25 @@ void test() { d->fn(); // expected-error {{attempt to use a deleted function}} int i = *d; // expected-error {{invokes a deleted function}} } + +struct DelDtor { + ~DelDtor() = delete; // expected-note 9{{here}} +}; +void f() { + DelDtor *p = new DelDtor[3]; // expected-error {{attempt to use a deleted function}} + delete [] p; // expected-error {{attempt to use a deleted function}} + const DelDtor &dd2 = DelDtor(); // expected-error {{attempt to use a deleted function}} + DelDtor dd; // expected-error {{attempt to use a deleted function}} + throw dd; // expected-error {{attempt to use a deleted function}} +} +struct X : DelDtor { + ~X() {} // expected-error {{attempt to use a deleted function}} +}; +struct Y { + DelDtor dd; + ~Y() {} // expected-error {{attempt to use a deleted function}} +}; +struct Z : virtual DelDtor { + ~Z() {} // expected-error {{attempt to use a deleted function}} +}; +DelDtor dd; // expected-error {{attempt to use a deleted function}} diff --git a/test/SemaCXX/deleted-operator.cpp b/test/SemaCXX/deleted-operator.cpp index e357401..0e0282a 100644 --- a/test/SemaCXX/deleted-operator.cpp +++ b/test/SemaCXX/deleted-operator.cpp @@ -11,3 +11,8 @@ int PR10757f() { if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 6 {{built-in candidate}} if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 81 {{built-in candidate}} } + +struct DelOpDel { + virtual ~DelOpDel() {} // expected-error {{deleted function}} + void operator delete(void*) = delete; // expected-note {{deleted here}} +}; diff --git a/test/SemaCXX/dependent-auto.cpp b/test/SemaCXX/dependent-auto.cpp index 1be1566..6d37f7a 100644 --- a/test/SemaCXX/dependent-auto.cpp +++ b/test/SemaCXX/dependent-auto.cpp @@ -8,7 +8,7 @@ struct only { template<typename ...T> void f(T ...t) { - auto x(t...); // expected-error {{requires an initializer}} expected-error {{contains multiple expressions}} + auto x(t...); // expected-error {{is empty}} expected-error {{contains multiple expressions}} only<int> check = x; } diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index 14a0cda..f3c6ab0 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -16,7 +16,7 @@ public: struct D { static void ~D(int, ...) const { } // \ - // expected-error{{type qualifier is not allowed on this function}} \ + // expected-error{{static member function cannot have 'const' qualifier}} \ // expected-error{{destructor cannot be declared 'static'}} \ // expected-error{{destructor cannot have any parameters}} \ // expected-error{{destructor cannot be variadic}} \ diff --git a/test/SemaCXX/discrim-union.cpp b/test/SemaCXX/discrim-union.cpp new file mode 100644 index 0000000..15c9a22 --- /dev/null +++ b/test/SemaCXX/discrim-union.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -std=c++11 %s -fsyntax-only -fcxx-exceptions + +template<typename T> struct remove_reference { typedef T type; }; +template<typename T> struct remove_reference<T&> { typedef T type; }; +template<typename T> struct remove_reference<T&&> { typedef T type; }; + +template<typename T> constexpr T &&forward(typename remove_reference<T>::type &t) noexcept { return static_cast<T&&>(t); } +template<typename T> constexpr T &&forward(typename remove_reference<T>::type &&t) noexcept { return static_cast<T&&>(t); } +template<typename T> constexpr typename remove_reference<T>::type &&move(T &&t) noexcept { return static_cast<typename remove_reference<T>::type&&>(t); } + +template<typename T> T declval() noexcept; + +namespace detail { + template<unsigned N> struct select {}; // : integral_constant<unsigned, N> {}; + template<typename T> struct type {}; + + template<typename...T> union either_impl; + + template<> union either_impl<> { + void get(...); + void destroy(...) { throw "logic_error"; } + }; + + template<typename T, typename...Ts> union either_impl<T, Ts...> { + private: + T val; + either_impl<Ts...> rest; + typedef either_impl<Ts...> rest_t; + + public: + constexpr either_impl(select<0>, T &&t) : val(move(t)) {} + + template<unsigned N, typename U> + constexpr either_impl(select<N>, U &&u) : rest(select<N-1>(), move(u)) {} + + constexpr static unsigned index(type<T>) { return 0; } + template<typename U> + constexpr static unsigned index(type<U> t) { + return decltype(rest)::index(t) + 1; + } + + void destroy(unsigned elem) { + if (elem) + rest.destroy(elem - 1); + else + val.~T(); + } + + constexpr const T &get(select<0>) { return val; } + template<unsigned N> constexpr const decltype(static_cast<const rest_t&>(rest).get(select<N-1>{})) get(select<N>) { + return rest.get(select<N-1>{}); + } + }; +} + +template<typename T> +struct a { + T value; + template<typename...U> + constexpr a(U &&...u) : value{forward<U>(u)...} {} +}; +template<typename T> using an = a<T>; + +template<typename T, typename U> T throw_(const U &u) { throw u; } + +template<typename...T> +class either { + unsigned elem; + detail::either_impl<T...> impl; + typedef decltype(impl) impl_t; + +public: + template<typename U> + constexpr either(a<U> &&t) : + elem(impl_t::index(detail::type<U>())), + impl(detail::select<impl_t::index(detail::type<U>())>(), move(t.value)) {} + + // Destruction disabled to allow use in a constant expression. + // FIXME: declare a destructor iff any element has a nontrivial destructor + //~either() { impl.destroy(elem); } + + constexpr unsigned index() noexcept { return elem; } + + template<unsigned N> using const_get_result = + decltype(static_cast<const impl_t&>(impl).get(detail::select<N>{})); + + template<unsigned N> + constexpr const_get_result<N> get() { + // Can't just use throw here, since that makes the conditional a prvalue, + // which means we return a reference to a temporary. + return (elem != N ? throw_<const_get_result<N>>("bad_either_get") + : impl.get(detail::select<N>{})); + } + + template<typename U> + constexpr const U &get() { + return get<impl_t::index(detail::type<U>())>(); + } +}; + +typedef either<int, char, double> icd; +constexpr icd icd1 = an<int>(4); +constexpr icd icd2 = a<char>('x'); +constexpr icd icd3 = a<double>(6.5); + +static_assert(icd1.get<int>() == 4, ""); +static_assert(icd2.get<char>() == 'x', ""); +static_assert(icd3.get<double>() == 6.5, ""); + +struct non_triv { + constexpr non_triv() : n(5) {} + int n; +}; +constexpr either<const icd*, non_triv> icd4 = a<const icd*>(&icd2); +constexpr either<const icd*, non_triv> icd5 = a<non_triv>(); + +static_assert(icd4.get<const icd*>()->get<char>() == 'x', ""); +static_assert(icd5.get<non_triv>().n == 5, ""); diff --git a/test/SemaCXX/dr1301.cpp b/test/SemaCXX/dr1301.cpp new file mode 100644 index 0000000..ec0db74 --- /dev/null +++ b/test/SemaCXX/dr1301.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s +struct A { // expected-note 2{{candidate}} + A(int); // expected-note {{candidate}} + int n; +}; +int a = A().n; // expected-error {{no matching constructor}} + +struct B { + B() = delete; // expected-note 3{{here}} + int n; +}; +int b = B().n; // expected-error {{call to deleted}} + +struct C { + B b; // expected-note {{deleted default constructor}} +}; +int c = C().b.n; // expected-error {{call to implicitly-deleted default}} + +struct D { + D() = default; // expected-note {{here}} + B b; // expected-note {{'b' has a deleted default constructor}} +}; +int d = D().b.n; // expected-error {{call to implicitly-deleted default}} + +struct E { + E() = default; + int n; +}; +int e = E().n; // ok + +struct F { + F(); + int n; +}; +int f = F().n; // ok + +union G { + F f; // expected-note {{non-trivial default constructor}} +}; +int g = G().f.n; // expected-error {{call to implicitly-deleted default}} + +struct H { + int n; +private: + H(); // expected-note {{here}} +}; +int h = H().n; // expected-error {{private constructor}} + +struct I { + H h; // expected-note {{inaccessible default constructor}} +}; +int i = I().h.n; // expected-error {{call to implicitly-deleted default}} + +struct J { + J(); + virtual int f(); + int n; +}; +int j1 = J().n; // ok +int j2 = J().f(); // ok + +union K { + J j; // expected-note 2{{non-trivial default constructor}} + int m; +}; +int k1 = K().j.n; // expected-error {{call to implicitly-deleted default}} +int k2 = K().j.f(); // expected-error {{call to implicitly-deleted default}} diff --git a/test/SemaCXX/empty-class-layout.cpp b/test/SemaCXX/empty-class-layout.cpp index 0b46bf0..c68f2bb 100644 --- a/test/SemaCXX/empty-class-layout.cpp +++ b/test/SemaCXX/empty-class-layout.cpp @@ -144,3 +144,14 @@ struct B : Empty, A { }; SA(0, sizeof(B) == 16); } + +namespace Test7 { + // Make sure we reserve enough space for both bases; PR11745. + struct Empty { }; + struct Base1 : Empty { }; + struct Base2 : Empty { }; + struct Test : Base1, Base2 { + char c; + }; + SA(0, sizeof(Test) == 2); +} diff --git a/test/SemaCXX/enum-bitfield.cpp b/test/SemaCXX/enum-bitfield.cpp index 1a65740..63445ca 100644 --- a/test/SemaCXX/enum-bitfield.cpp +++ b/test/SemaCXX/enum-bitfield.cpp @@ -14,5 +14,5 @@ struct X { struct Y { enum E : int(2); - enum E : Z(); // expected-error{{not an integer constant}} + enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}} }; diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index 35ba1b4..ebe9245 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -34,12 +34,12 @@ int a1[Val2]; int a2[E1::Val1]; // expected-error{{size of array has non-integer type}} int* p1 = new int[Val2]; -int* p2 = new int[E1::Val1]; // FIXME Expected-error{{must have integral}} +int* p2 = new int[E1::Val1]; // expected-error{{array size expression must have integral or unscoped enumeration type, not 'E1'}} enum class E4 { e1 = -2147483648, // ok e2 = 2147483647, // ok - e3 = 2147483648 // expected-error{{value is not representable}} + e3 = 2147483648 // expected-error{{enumerator value evaluates to 2147483648, which cannot be narrowed to type 'int'}} }; enum class E5 { @@ -142,3 +142,106 @@ namespace test6 { (void) A::e; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} } } + +namespace PR11484 { + const int val = 104; + enum class test1 { owner_dead = val, }; +} + +namespace N2764 { + enum class E { a, b }; + enum E x1 = E::a; // ok + enum class E x2 = E::a; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}} + + enum F { a, b }; + enum F y1 = a; // ok + enum class F y2 = a; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}} + + struct S { + friend enum class E; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}} + friend enum class F; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}} + + friend enum G {}; // expected-error {{forward reference}} expected-error {{cannot define a type in a friend declaration}} + friend enum class H {}; // expected-error {{cannot define a type in a friend declaration}} + + enum A : int; + A a; + } s; + + enum S::A : int {}; + + enum class B; +} + +enum class N2764::B {}; + +namespace PR12106 { + template<typename E> struct Enum { + Enum() : m_e(E::Last) {} + E m_e; + }; + + enum eCOLORS { Last }; + Enum<eCOLORS> e; +} + +namespace test7 { + enum class E { e = (struct S*)0 == (struct S*)0 }; + S *p; +} + +namespace test8 { + template<typename T> struct S { + enum A : int; // expected-note {{here}} + enum class B; // expected-note {{here}} + enum class C : int; // expected-note {{here}} + enum class D : int; // expected-note {{here}} + }; + template<typename T> enum S<T>::A { a }; // expected-error {{previously declared with fixed underlying type}} + template<typename T> enum class S<T>::B : char { b }; // expected-error {{redeclared with different underlying}} + template<typename T> enum S<T>::C : int { c }; // expected-error {{previously declared as scoped}} + template<typename T> enum class S<T>::D : char { d }; // expected-error {{redeclared with different underlying}} +} + +namespace test9 { + template<typename T> struct S { + enum class ET : T; // expected-note 2{{here}} + enum class Eint : int; // expected-note 2{{here}} + }; + template<> enum class S<int>::ET : int {}; + template<> enum class S<char>::ET : short {}; // expected-error {{different underlying type}} + template<> enum class S<int>::Eint : short {}; // expected-error {{different underlying type}} + template<> enum class S<char>::Eint : int {}; + + template<typename T> enum class S<T>::ET : int {}; // expected-error {{different underlying type 'int' (was 'short')}} + template<typename T> enum class S<T>::Eint : T {}; // expected-error {{different underlying type 'short' (was 'int')}} + + // The implicit instantiation of S<short> causes the implicit instantiation of + // all declarations of member enumerations, so is ill-formed, even though we + // never instantiate the definitions of S<short>::ET nor S<short>::Eint. + S<short> s; // expected-note {{in instantiation of}} +} + +namespace test10 { + template<typename T> int f() { + enum E : int; + enum E : T; // expected-note {{here}} + E x; + enum E : int { e }; // expected-error {{different underlying}} + x = e; + return x; + } + int k = f<int>(); + int l = f<short>(); // expected-note {{here}} + + template<typename T> int g() { + enum class E : int; + enum class E : T; // expected-note {{here}} + E x; + enum class E : int { e }; // expected-error {{different underlying}} + x = E::e; + return (int)x; + } + int m = g<int>(); + int n = g<short>(); // expected-note {{here}} +} diff --git a/test/SemaCXX/enum-unscoped-nonexistent.cpp b/test/SemaCXX/enum-unscoped-nonexistent.cpp new file mode 100644 index 0000000..d49800c --- /dev/null +++ b/test/SemaCXX/enum-unscoped-nonexistent.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +struct Base { + static const int a = 1; +}; +template<typename T> struct S : Base { + enum E : int; + constexpr int f(); + constexpr int g(); // expected-note {{declared here}} + void h(); +}; +template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}} +template<> enum S<short>::E : int { b = 2 }; +template<> enum S<int>::E : int { a = 4 }; +template<typename T> enum S<T>::E : int { b = 8 }; + +// The unqualified-id here names a member of the non-dependent base class Base +// and not the injected enumerator name 'a' from the specialization. +template<typename T> constexpr int S<T>::f() { return a; } +static_assert(S<char>().f() == 1, ""); +static_assert(S<int>().f() == 1, ""); + +// The unqualified-id here names a member of the current instantiation, which +// bizarrely might not exist in some instantiations. +template<typename T> constexpr int S<T>::g() { return b; } // expected-error {{enumerator 'b' does not exist in instantiation of 'S<char>'}} +static_assert(S<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} expected-note {{undefined}} +static_assert(S<short>().g() == 2, ""); +static_assert(S<long>().g() == 8, ""); + +// 'b' is type-dependent, so these assertions should not fire before 'h' is +// instantiated. +template<typename T> void S<T>::h() { + char c[S<T>::b]; + static_assert(b != 8, ""); + static_assert(sizeof(c) != 8, ""); +} +void f() { + S<short>().h(); // ok, b == 2 +} diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp index b4a050c..370e1c3 100644 --- a/test/SemaCXX/enum.cpp +++ b/test/SemaCXX/enum.cpp @@ -88,7 +88,7 @@ typedef enum { }; // expected-warning{{typedef requires a name}} // PR7921 enum PR7921E { - PR7921V = (PR7921E)(123) // expected-error {{expression is not an integer constant expression}} + PR7921V = (PR7921E)(123) // expected-error {{expression is not an integral constant expression}} }; void PR8089() { diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp index e2bfe18..486d88e 100644 --- a/test/SemaCXX/exceptions.cpp +++ b/test/SemaCXX/exceptions.cpp @@ -12,8 +12,8 @@ void trys() { } catch(float i) { } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}} } catch(A a) { // expected-error {{cannot catch incomplete type 'A'}} - } catch(A *a) { // expected-warning {{ISO C++ forbids catching a pointer to incomplete type 'A'}} - } catch(A &a) { // expected-warning {{ISO C++ forbids catching a reference to incomplete type 'A'}} + } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'A'}} + } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'A'}} } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}} } catch(...) { int j = i; // expected-error {{use of undeclared identifier 'i'}} @@ -35,37 +35,37 @@ void throws() { 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 l4; // expected-error {{goto into protected scope}} + goto l3; // expected-error {{goto into protected scope}} + goto l2; // expected-error {{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 l4; // expected-error {{goto into protected scope}} + goto l3; // expected-error {{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 l4; // expected-error {{goto into protected scope}} goto l3; - goto l2; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{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 l3; // expected-error {{goto into protected scope}} + goto l2; // expected-error {{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 l4; // expected-error {{goto into protected scope}} + goto l3; // expected-error {{goto into protected scope}} + goto l2; // expected-error {{goto into protected scope}} goto l1; } diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp index 11b9672..4774637 100644 --- a/test/SemaCXX/explicit.cpp +++ b/test/SemaCXX/explicit.cpp @@ -43,16 +43,8 @@ namespace Conversion { class Y { }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \ expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \ expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \ - expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \ - expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \ - expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \ - expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \ - expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \ - expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \ - expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \ - expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \ - expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \ - expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} + struct Z { explicit operator Y() const; explicit operator int() const; @@ -61,10 +53,9 @@ namespace Conversion { Z z; // 13.3.1.4p1 & 8.5p16: Y y2 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'Conversion::Y'}} - // FIXME: These are well-formed per C++0x 13.3.1.4p1 (see DR899). - Y y3 = (Y)z; // expected-error {{no matching conversion for C-style cast from 'Conversion::Z' to 'Conversion::Y''}} - Y y4 = Y(z); // expected-error {{no matching conversion for functional-style cast from 'Conversion::Z' to 'Conversion::Y'}} - Y y5 = static_cast<Y>(z); // expected-error {{no matching conversion for static_cast from 'Conversion::Z' to 'Conversion::Y'}} + Y y3 = (Y)z; + Y y4 = Y(z); + Y y5 = static_cast<Y>(z); // 13.3.1.5p1 & 8.5p16: int i1 = (int)z; int i2 = int(z); diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 32b3ff9..2767d4a 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -185,8 +185,8 @@ struct Class : BaseClass template <class T> struct NestedClassTemplate {}; - template <class T> // expected-note{{possible target for call}} - static int& NestedFuncTemplate() { return variable; } + template <class T> + static int& NestedFuncTemplate() { return variable; } // expected-note{{possible target for call}} template <class T> int& NestedMemfunTemplate() { return variable; } diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index b994e8c..8bda510 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -148,3 +148,35 @@ int main() { } assert(total == 500); } + +// PR11793 +namespace test2 { + class A { + int xs[10]; // expected-note {{implicitly declared private here}} + }; + void test(A &a) { + for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}} + } +} + +namespace test3 { + // Make sure this doesn't crash + struct A {}; + struct B { ~B(); operator bool(); }; + struct C { B operator!=(const C&); C& operator++(); int operator*(); }; + C begin(const A&); + C end(const A&); + template<typename T> void f() { for (auto a : A()) {} } + void g() { f<int>(); } +} + +namespace test4 { + void f() { + int y; + + // Make sure these don't crash. Better diagnostics would be nice. + for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}} + for (x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} + for (y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} + } +} diff --git a/test/SemaCXX/for-range-no-std.cpp b/test/SemaCXX/for-range-no-std.cpp index dae41f1..fa42ca4 100644 --- a/test/SemaCXX/for-range-no-std.cpp +++ b/test/SemaCXX/for-range-no-std.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++0x-extensions +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions struct S { int *begin(); @@ -36,3 +36,8 @@ void f() { for (int b : NS::ADL()) {} // ok for (int b : NS::NoADL()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} } + +void PR11601() { + void (*vv[])() = {PR11601, PR11601, PR11601}; + for (void (*i)() : vv) i(); +} diff --git a/test/SemaCXX/format-strings-0x.cpp b/test/SemaCXX/format-strings-0x.cpp new file mode 100644 index 0000000..e7c5904 --- /dev/null +++ b/test/SemaCXX/format-strings-0x.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -std=c++11 %s + +extern "C" { +extern int scanf(const char *restrict, ...); +extern int printf(const char *restrict, ...); +} + +void f(char **sp, float *fp) { + scanf("%as", sp); // expected-warning{{format specifies type 'float *' but the argument has type 'char **'}} + + printf("%a", 1.0); + scanf("%afoobar", fp); + printf(nullptr); + printf(*sp); // expected-warning {{not a string literal}} +} diff --git a/test/SemaCXX/format-strings.cpp b/test/SemaCXX/format-strings.cpp new file mode 100644 index 0000000..6b0df29 --- /dev/null +++ b/test/SemaCXX/format-strings.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -pedantic %s + +#include <stdarg.h> + +extern "C" { +extern int scanf(const char *restrict, ...); +extern int printf(const char *restrict, ...); +extern int vprintf(const char *restrict, va_list); +} + +void f(char **sp, float *fp) { + scanf("%as", sp); // expected-warning{{'a' length modifier is not supported by ISO C}} + + // TODO: Warn that the 'a' conversion specifier is a C++11 feature. + printf("%a", 1.0); + scanf("%afoobar", fp); +} + +void g() { + printf("%ls", "foo"); // expected-warning{{format specifies type 'wchar_t *' but the argument has type 'const char *'}} +} + +// Test that we properly handle format_idx on C++ members. +class Foo { +public: + const char *gettext(const char *fmt) __attribute__((format_arg(2))); + + int scanf(const char *, ...) __attribute__((format(scanf, 2, 3))); + int printf(const char *, ...) __attribute__((format(printf, 2, 3))); + int printf2(const char *, ...); + + static const char *gettext_static(const char *fmt) __attribute__((format_arg(1))); + static int printf_static(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +}; + +void h(int *i) { + Foo foo; + foo.scanf("%d"); // expected-warning{{more '%' conversions than data arguments}} + foo.printf("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} + Foo::printf_static("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} + + printf(foo.gettext("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} + printf(Foo::gettext_static("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}} +} + +// Test handling __null for format string literal checking. +extern "C" { + int test_null_format(const char *format, ...) __attribute__((__format__ (__printf__, 1, 2))); +} + +void rdar8269537(const char *f) +{ + test_null_format(false); // expected-warning {{null from a constant boolean}} + test_null_format(0); // no-warning + test_null_format(__null); // no-warning + test_null_format(f); // expected-warning {{not a string literal}} +} + +int Foo::printf(const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + const char * const format = fmt; + vprintf(format, ap); // no-warning + + const char *format2 = fmt; + vprintf(format2, ap); // expected-warning{{format string is not a string literal}} + + return 0; +} + +int Foo::printf2(const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + vprintf(fmt, ap); // expected-warning{{format string is not a string literal}} + + return 0; +} diff --git a/test/SemaCXX/friend-out-of-line.cpp b/test/SemaCXX/friend-out-of-line.cpp new file mode 100644 index 0000000..56b2daa --- /dev/null +++ b/test/SemaCXX/friend-out-of-line.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/10204947> +namespace N { + class X; +}; + +class N::X { + template<typename T> friend const T& f(const X&); + friend const int& g(const X&); + friend class Y; +}; diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp index b1ef220..c5b11eb 100644 --- a/test/SemaCXX/friend.cpp +++ b/test/SemaCXX/friend.cpp @@ -130,3 +130,11 @@ namespace test6_3 { v.f(); } } + +namespace test7 { + extern "C" { + class X { + friend int f() { return 42; } + }; + } +} diff --git a/test/SemaCXX/function-extern-c.cpp b/test/SemaCXX/function-extern-c.cpp new file mode 100644 index 0000000..f20cd38 --- /dev/null +++ b/test/SemaCXX/function-extern-c.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -Wreturn-type -fsyntax-only -std=c++11 -verify %s + +class A { +public: + A(const A&); +}; + +struct S { + int i; + double d; + + virtual void B() {} +}; + +union U { + struct { + int i; + virtual void B() {} // Can only do this in C++11 + } t; +}; + +struct S2 { + int i; + double d; +}; + +extern "C" U f3( void ); // expected-warning {{'f3' has C-linkage specified, but returns user-defined type 'U' which is incompatible with C}} +extern "C" S f0(void); // expected-warning {{'f0' has C-linkage specified, but returns user-defined type 'S' which is incompatible with C}} +extern "C" A f4( void ); // expected-warning {{'f4' has C-linkage specified, but returns user-defined type 'A' which is incompatible with C}} + +// These should all be fine +extern "C" S2 f5( void ); +extern "C" void f2( A x ); +extern "C" void f6( S s ); +extern "C" void f7( U u ); +extern "C" double f8(void); +extern "C" long long f11( void ); +extern "C" A *f10( void ); diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp index 0d9ecf3..0eb109d 100644 --- a/test/SemaCXX/function-redecl.cpp +++ b/test/SemaCXX/function-redecl.cpp @@ -76,9 +76,12 @@ class Crash { void GetCart(int count) const; }; // This out-of-line definition was fine... -void Crash::cart(int count) const {} // expected-error {{out-of-line definition of 'cart' does not match any declaration in 'Crash'}} +void Crash::cart(int count) const {} // expected-error {{out-of-line definition of 'cart' does not match any declaration in 'Crash'}} \ + // expected-note {{'cart' declared here}} \ + // expected-note {{previous definition is here}} // ...while this one crashed clang -void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'}} +void Crash::chart(int count) const {} // expected-error {{out-of-line definition of 'chart' does not match any declaration in 'Crash'; did you mean 'cart'?}} \ + // expected-error {{redefinition of 'cart'}} class TestConst { public: diff --git a/test/SemaCXX/function-type-qual.cpp b/test/SemaCXX/function-type-qual.cpp index 8ebb506..73613ae 100644 --- a/test/SemaCXX/function-type-qual.cpp +++ b/test/SemaCXX/function-type-qual.cpp @@ -1,17 +1,17 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -void f() const; // expected-error {{type qualifier is not allowed on this function}} -void (*pf)() const; // expected-error {{type qualifier is not allowed on this function pointer}} -void (&rf)() const = f; // expected-error {{type qualifier is not allowed on this function reference}} +void f() const; // expected-error {{non-member function cannot have 'const' qualifier}} +void (*pf)() const; // expected-error {{pointer to function type cannot have 'const' qualifier}} +extern void (&rf)() const; // expected-error {{reference to function type cannot have 'const' qualifier}} -typedef void cfn() const; -cfn f2; // expected-error {{a qualified function type cannot be used to declare a nonmember function}} +typedef void cfn() const; +cfn f2; // expected-error {{non-member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}} 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 static member function}} + static void f3() const; // expected-error {{static member function cannot have 'const' qualifier}} + static cfn f4; // expected-error {{static member function of type 'cfn' (aka 'void () const') cannot have 'const' qualifier}} void m1() { x = 0; diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp deleted file mode 100644 index a1891c9..0000000 --- a/test/SemaCXX/generalized-initializers.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -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 { - - int function_call() { - void takes_int(int); - takes_int({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}) {} - } - -} - -namespace objects { - - struct X1 { X1(int); }; - struct X2 { explicit X2(int); }; - - template <int N> - struct A { - A() { static_assert(N == 0, ""); } - A(int, double) { static_assert(N == 1, ""); } - A(std::initializer_list<int>) { static_assert(N == 3, ""); } - }; - - template <int N> - struct D { - D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}} - D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}} - }; - - template <int N> - struct E { - E(int, int) { static_assert(N == 0, ""); } - E(X1, int) { static_assert(N == 1, ""); } - }; - - void overload_resolution() { - { A<0> a{}; } - { A<0> a = {}; } - // Narrowing conversions don't affect viability. The next two choose - // the initializer_list constructor. - { A<3> a{1, 1.0}; } // expected-error {{narrowing conversion}} - { A<3> a = {1, 1.0}; } // expected-error {{narrowing conversion}} - { 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}; } - - { D<0> d{1, 2, 3}; } - { D<1> d{1.0, 2.0, 3.0}; } - { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}} - - { E<0> e{1, 2}; } - } - - void explicit_implicit() { - { X1 x{0}; } - { X1 x = {0}; } - { X2 x{0}; } - { X2 x = {0}; } // expected-error {{explicit}} - } - - 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}); - -} - -namespace aggregate { - // Direct list initialization does NOT allow braces to be elided! - struct S { - int ar[2]; - struct T { - int i1; - int i2; - } t; - struct U { - int i1; - } u[2]; - struct V { - int var[2]; - } v; - }; - - void test() { - S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error - S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced - S s3{ 1, 2, 3, 4, 5, 6 }; // xpected-error - S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // xpected-error - S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // xpected-error - } -} diff --git a/test/SemaCXX/gnu-case-ranges.cpp b/test/SemaCXX/gnu-case-ranges.cpp index c1c18a8..b082e3a 100644 --- a/test/SemaCXX/gnu-case-ranges.cpp +++ b/test/SemaCXX/gnu-case-ranges.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify -Wno-covered-switch-default %s enum E { one, diff --git a/test/SemaCXX/goto.cpp b/test/SemaCXX/goto.cpp index d8d5ec5..24bcb7c 100644 --- a/test/SemaCXX/goto.cpp +++ b/test/SemaCXX/goto.cpp @@ -103,3 +103,25 @@ void f() { exit: return; } + +namespace PR10620 { + struct S { + ~S() {} + }; + void g(const S& s) { + goto done; // expected-error {{goto into protected scope}} + const S s2(s); // expected-note {{jump bypasses variable initialization}} + done: + ; + } +} + +namespace test12 { + struct A { A(); A(const A&); ~A(); }; + void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: wierd location + goto lbl; // expected-error {{goto into protected scope}} + (void) ^{ (void) a; }; + lbl: + return; + } +} diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index 4d02ca8..5631577 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s // C++-specific tests for integral constant expressions. @@ -16,9 +16,9 @@ void f() { } int a() { - const int t=t; + const int t=t; // expected-note {{declared here}} switch(1) { // expected-warning {{no case matching constant switch condition '1'}} - case t:; // expected-error {{not an integer constant expression}} + case t:; // expected-error {{not an integral constant expression}} expected-note {{initializer of 't' is not a constant expression}} } } @@ -48,7 +48,7 @@ void pr6373(const unsigned x = 0) { namespace rdar9204520 { struct A { - static const int B = int(0.75 * 1000 * 1000); + static const int B = int(0.75 * 1000 * 1000); // expected-warning {{not a constant expression; folding it to a constant is a GNU extension}} }; int foo() { return A::B; } @@ -59,5 +59,10 @@ const int x = 10; int* y = reinterpret_cast<const char&>(x); // expected-error {{cannot initialize}} // This isn't an integral constant expression, but make sure it folds anyway. -struct PR8836 { char _; long long a; }; -int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; +struct PR8836 { char _; long long a; }; // expected-warning {{long long}} +int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + +const int nonconst = 1.0; // expected-note {{declared here}} +int arr[nonconst]; // expected-warning {{folded to constant array as an extension}} expected-note {{initializer of 'nonconst' is not a constant expression}} +const int castfloat = static_cast<int>(1.0); +int arr2[castfloat]; // ok diff --git a/test/SemaCXX/if-empty-body.cpp b/test/SemaCXX/if-empty-body.cpp deleted file mode 100644 index ec7f89d..0000000 --- a/test/SemaCXX/if-empty-body.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -void f1(int a) { - if (a); // expected-warning {{if statement has empty body}} -} - -void f2(int a) { - if (a) {} -} - -void f3() { - if (1) - xx; // expected-error {{use of undeclared identifier}} - return; // no empty body warning. -} - -// Don't warn about an empty body if is expanded from a macro. -void f4(int i) { - #define BODY(x) - if (i == i) // expected-warning{{self-comparison always evaluates to true}} - BODY(0); - #undef BODY -} - -template <typename T> -void tf() { - #define BODY(x) - if (0) - BODY(0); - #undef BODY -} - -void f5() { - tf<int>(); -} diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp index 559c301..786e8f4 100644 --- a/test/SemaCXX/implicit-exception-spec.cpp +++ b/test/SemaCXX/implicit-exception-spec.cpp @@ -54,10 +54,9 @@ namespace ExceptionSpecification { // 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 Default { struct T { - T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to deleted constructor}} - } t; + T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to implicitly-deleted default constructor}} + } t; // expected-note {{has no default constructor}} }; } diff --git a/test/SemaCXX/incomplete-call.cpp b/test/SemaCXX/incomplete-call.cpp index d627c33..69eb03a 100644 --- a/test/SemaCXX/incomplete-call.cpp +++ b/test/SemaCXX/incomplete-call.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s struct A; // expected-note 14 {{forward declaration of 'A'}} -A f(); // expected-note {{note: 'f' declared here}} +A f(); // expected-note {{'f' declared here}} struct B { A f(); // expected-note {{'f' declared here}} diff --git a/test/SemaCXX/indirect-goto.cpp b/test/SemaCXX/indirect-goto.cpp new file mode 100644 index 0000000..5b3fac4 --- /dev/null +++ b/test/SemaCXX/indirect-goto.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test1 { + // Make sure this doesn't crash. + struct A { ~A(); }; + void a() { goto *(A(), &&L); L: return; } +} diff --git a/test/SemaCXX/instantiate-blocks.cpp b/test/SemaCXX/instantiate-blocks.cpp index a4001a7..bb0f8d8 100644 --- a/test/SemaCXX/instantiate-blocks.cpp +++ b/test/SemaCXX/instantiate-blocks.cpp @@ -12,8 +12,21 @@ template <typename T, typename T1> void foo(T t, T1 r) return block_arg+arg; }; } +// rdar://10466373 +template <typename T, typename T1> void noret(T t, T1 r) +{ + (void) ^{ + if (1) + return t; + else if (2) + return r; // expected-error {{return type 'double' must match previous return type 'float' when block literal has unspecified explicit return type}} + }; +} + int main(void) { foo(100, 'a'); // expected-note {{in instantiation of function template specialization 'foo<int, char>' requested here}} + + noret((float)0.0, double(0.0)); // expected-note {{in instantiation of function template specialization 'noret<float, double>' requested here}} } diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp index 37025d9..287d9af 100644 --- a/test/SemaCXX/invalid-member-expr.cpp +++ b/test/SemaCXX/invalid-member-expr.cpp @@ -8,7 +8,7 @@ void test() { x.int; // expected-error{{expected unqualified-id}} x.~int(); // expected-error{{expected a class name}} x.operator; // expected-error{{expected a type}} - x.operator typedef; // expected-error{{expected a type}} + x.operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}} } void test2() { @@ -17,7 +17,7 @@ void test2() { x->int; // expected-error{{expected unqualified-id}} x->~int(); // expected-error{{expected a class name}} x->operator; // expected-error{{expected a type}} - x->operator typedef; // expected-error{{expected a type}} + x->operator typedef; // expected-error{{expected a type}} expected-error{{type name does not allow storage class}} } // PR6327 diff --git a/test/SemaCXX/issue547.cpp b/test/SemaCXX/issue547.cpp index 5b82dc6..ab03a15 100644 --- a/test/SemaCXX/issue547.cpp +++ b/test/SemaCXX/issue547.cpp @@ -11,17 +11,17 @@ struct classify_function<R(Args...)> { }; template<typename R, typename ...Args> -struct classify_function<R(Args...) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}} +struct classify_function<R(Args...) const> { static const unsigned value = 2; }; template<typename R, typename ...Args> -struct classify_function<R(Args...) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}} +struct classify_function<R(Args...) volatile> { static const unsigned value = 3; }; template<typename R, typename ...Args> -struct classify_function<R(Args...) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}} +struct classify_function<R(Args...) const volatile> { static const unsigned value = 4; }; @@ -31,27 +31,27 @@ struct classify_function<R(Args......)> { }; template<typename R, typename ...Args> -struct classify_function<R(Args......) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}} +struct classify_function<R(Args......) const> { static const unsigned value = 6; }; template<typename R, typename ...Args> -struct classify_function<R(Args......) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}} +struct classify_function<R(Args......) volatile> { static const unsigned value = 7; }; template<typename R, typename ...Args> -struct classify_function<R(Args......) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}} +struct classify_function<R(Args......) const volatile> { static const unsigned value = 8; }; template<typename R, typename ...Args> -struct classify_function<R(Args......) &&> { // expected-warning{{template argument of '&&' qualified function type is a GNU extension}} +struct classify_function<R(Args......) &&> { static const unsigned value = 9; }; template<typename R, typename ...Args> -struct classify_function<R(Args......) const &> { // expected-warning{{template argument of 'const &' qualified function type is a GNU extension}} +struct classify_function<R(Args......) const &> { static const unsigned value = 10; }; diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp new file mode 100644 index 0000000..e91dee9 --- /dev/null +++ b/test/SemaCXX/lambda-expressions.cpp @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s + +namespace std { class type_info; }; + +namespace ExplicitCapture { + class C { + int Member; + + static void Overload(int); + void Overload(); + virtual C& Overload(float); + + void ImplicitThisCapture() { + [](){(void)Member;}; // expected-error {{'this' cannot be implicitly captured in this context}} + [&](){(void)Member;}; + + [this](){(void)Member;}; + [this]{[this]{};}; + []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}} + []{Overload(3);}; + []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}} + []{(void)typeid(Overload());}; + []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}} + } + }; + + void f() { + [this] () {}; // expected-error {{'this' cannot be captured in this context}} + } +} + +namespace ReturnDeduction { + void test() { + [](){ return 1; }; + [](){ return 1; }; + [](){ return ({return 1; 1;}); }; + [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} \ + // expected-warning{{omitted result type}} + []()->int{ return 'c'; return 1; }; + [](){ return 'c'; return 1; }; // expected-error {{must match previous return type}} + []() { return; return (void)0; }; + [](){ return 1; return 1; }; // expected-warning{{omitted result type}} + } +} + +namespace ImplicitCapture { + void test() { + int a = 0; // expected-note 5 {{declared}} + []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} + [&]() { return a; }; + [=]() { return a; }; + [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}} + [=]() { return [&]() { return a; }; }; + []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} + [=]() { return [&a] { return a; }; }; // + + const int b = 2; + []() { return b; }; + + union { // expected-note {{declared}} + int c; + float d; + }; + d = 3; + [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} + + __block int e; // expected-note 3 {{declared}} + [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}} + [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}} + + int f[10]; // expected-note {{declared}} + [&]() { return f[2]; }; + (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \ + // expected-note{{lambda expression begins here}} + + struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}} + G g; + [=]() { const G* gg = &g; return gg->a; }; // expected-warning{{omitted result type}} + [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}} \ + // expected-warning{{omitted result type}} + (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}} \ + // expected-warning{{omitted result type}} + + const int h = a; // expected-note {{declared}} + []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + + // The exemption for variables which can appear in constant expressions + // applies only to objects (and not to references). + // FIXME: This might be a bug in the standard. + static int i; + constexpr int &ref_i = i; // expected-note {{declared}} + [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + } +} + +namespace PR12031 { + struct X { + template<typename T> + X(const T&); + ~X(); + }; + + void f(int i, X x); + void g() { + const int v = 10; + f(v, [](){}); + } +} + +namespace NullPtr { + int &f(int *p); + char &f(...); + void g() { + int n = 0; + [=] { + char &k = f(n); // not a null pointer constant + } (); + + const int m = 0; + [=] { + int &k = f(m); // a null pointer constant + } (); + + [=] () -> bool { + int &k = f(m); // a null pointer constant + return &m == 0; + } (); + + [m] { + int &k = f(m); // a null pointer constant + } (); + } +} + +void PR12248() +{ + unsigned int result = 0; + auto l = [&]() { ++result; }; +} + +namespace ModifyingCapture { + void test() { + int n = 0; + [=] { + n = 1; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} + }; + } +} diff --git a/test/SemaCXX/literal-operators.cpp b/test/SemaCXX/literal-operators.cpp index 06ef49f..7f68cd3 100644 --- a/test/SemaCXX/literal-operators.cpp +++ b/test/SemaCXX/literal-operators.cpp @@ -13,7 +13,7 @@ namespace ns { void operator "" _ns_good (const char *); } extern "C++" void operator "" _extern_good (const char *); extern "C++" { void operator "" _extern_good (const char *); } -void fn () { void operator "" _fn_bad (const char *); } // expected-error {{literal operator 'operator "" _fn_bad' must be in a namespace or global scope}} +void fn () { void operator "" _fn_good (const char *); } // One-param declarations (const char * was already checked) void operator "" _good (char); @@ -35,9 +35,9 @@ typedef const char c; void operator "" _good (c*); // Check extra cv-qualifiers -void operator "" _cv_good (volatile const char *, const size_t); +void operator "" _cv_good (volatile const char *, const size_t); // expected-error {{parameter declaration for literal operator 'operator "" _cv_good' is not valid}} -// Template delcaration (not implemented yet) -// template <char...> void operator "" good (); +// Template declaration +template <char...> void operator "" _good (); // FIXME: Test some invalid decls that might crop up. diff --git a/test/SemaCXX/literal-type.cpp b/test/SemaCXX/literal-type.cpp index 60bfcf0..14a4094 100644 --- a/test/SemaCXX/literal-type.cpp +++ b/test/SemaCXX/literal-type.cpp @@ -23,6 +23,8 @@ static_assert(__is_literal(VectorExt), "fail"); // a constant expression, // -- it is an aggregate type or has at least one constexpr constructor // or constructor template that is not a copy or move constructor, and +// [DR1452 adds class types with trivial default constructors to +// this list] // -- it has all non-static data members and base classes of literal // types struct Empty {}; @@ -36,25 +38,26 @@ struct LiteralType { struct HasDtor { ~HasDtor(); }; class NonAggregate { int x; }; -struct HasNonLiteralBase : NonAggregate {}; +struct NonLiteral { NonLiteral(); }; +struct HasNonLiteralBase : NonLiteral {}; struct HasNonLiteralMember { HasDtor x; }; static_assert(__is_literal(Empty), "fail"); static_assert(__is_literal(LiteralType), "fail"); +static_assert(__is_literal(NonAggregate), "fail"); +static_assert(!__is_literal(NonLiteral), "fail"); static_assert(!__is_literal(HasDtor), "fail"); -static_assert(!__is_literal(NonAggregate), "fail"); static_assert(!__is_literal(HasNonLiteralBase), "fail"); static_assert(!__is_literal(HasNonLiteralMember), "fail"); -// FIXME: Test constexpr constructors and non-static members with initializers -// when Clang supports them: -#if 0 -extern int f(); +// DR1361 removes the brace-or-equal-initializer bullet so that we can allow: +extern int f(); // expected-note {{here}} struct HasNonConstExprMemInit { - int x = f(); - constexpr HasNonConstExprMemInit(int y) {} + int x = f(); // expected-note {{non-constexpr function}} + constexpr HasNonConstExprMemInit() {} // expected-error {{never produces a constant expression}} + constexpr HasNonConstExprMemInit(int y) : x(y) {} // ok }; -static_assert(!__is_literal(HasNonConstExprMemInit), "fail"); +static_assert(__is_literal(HasNonConstExprMemInit), "fail"); class HasConstExprCtor { int x; @@ -66,6 +69,9 @@ template <typename T> class HasConstExprCtorTemplate { public: template <typename U> constexpr HasConstExprCtorTemplate(U y) : x(y) {} }; +template <typename T> class HasConstExprCtorT { + constexpr HasConstExprCtorT(T) {} +}; static_assert(__is_literal(HasConstExprCtor), "fail"); -static_assert(__is_literal(HasConstExprCtorTemplate), "fail"); -#endif +static_assert(__is_literal(HasConstExprCtorTemplate<int>), "fail"); +static_assert(__is_literal(HasConstExprCtorT<NonLiteral>), "fail"); diff --git a/test/SemaCXX/member-class-11.cpp b/test/SemaCXX/member-class-11.cpp new file mode 100644 index 0000000..c230c53 --- /dev/null +++ b/test/SemaCXX/member-class-11.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct rdar9677163 { + struct Y { ~Y(); }; + struct Z { ~Z(); }; + Y::~Y() { } // expected-error{{non-friend class member '~Y' cannot have a qualified name}} + ~Z(); // expected-error{{expected the class name after '~' to name the enclosing class}} +}; diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 2e3fd73..dbddd1c 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -94,11 +94,11 @@ namespace test5 { namespace PR7508 { struct A { struct CleanupScope {}; - void PopCleanupBlock(); + void PopCleanupBlock(); // expected-note{{'PopCleanupBlock' declared here}} }; void foo(A &a) { - a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'}} + a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'; did you mean 'PopCleanupBlock'?}} } } @@ -147,3 +147,13 @@ namespace PR9025 { return fun5.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } } + +namespace FuncInMemberExpr { + struct Vec { int size(); }; + Vec fun1(); + int test1() { return fun1.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} + Vec *fun2(); + int test2() { return fun2->size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} + Vec fun3(int x = 0); + int test3() { return fun3.size(); } // expected-error {{base of member reference is a function; perhaps you meant to call it with no arguments}} +} diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 819c8d1..c93c85b 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -29,6 +29,9 @@ 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}} + // test that we handle invalid array bound deductions without crashing when the declarator name is itself invalid + operator int[](){}; // expected-error {{'operator int' cannot be the name of a variable or data member}} \ + // expected-error {{array bound cannot be deduced from an in-class initializer}} }; struct ThrowCtor { ThrowCtor(int) noexcept(false); }; diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index cf64810..4e8b4a8 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -278,7 +278,7 @@ namespace PR9973 { 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>'}} + { return u->*f_; } // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} template<class U> int operator()(U u) { call(u); } // expected-note{{in instantiation of}} diff --git a/test/SemaCXX/microsoft-cxx0x.cpp b/test/SemaCXX/microsoft-cxx0x.cpp index 3f78eda..3b9bbef 100644 --- a/test/SemaCXX/microsoft-cxx0x.cpp +++ b/test/SemaCXX/microsoft-cxx0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++0x-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11 +// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wc++11-narrowing -Wmicrosoft -verify -fms-extensions -std=c++11 struct A { @@ -6,5 +6,3 @@ struct A { }; int b = 3; A var = { b }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} - - diff --git a/test/SemaCXX/missing-header.cpp b/test/SemaCXX/missing-header.cpp index f436579..5b3915b 100644 --- a/test/SemaCXX/missing-header.cpp +++ b/test/SemaCXX/missing-header.cpp @@ -2,8 +2,8 @@ #include "not exist" // expected-error{{'not exist' file not found}} -class AnalysisContext {}; -static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { +class AnalysisDeclContext {}; +static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {} bool NoReturnEdge = false; } diff --git a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp index 76ceea1..83f8395 100644 --- a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp +++ b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp @@ -1,15 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s namespace fizbin { class Foobar {}; } // expected-note 2 {{'fizbin::Foobar' declared here}} \ // expected-note {{'Foobar' declared here}} Foobar *my_bar // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} -fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{unknown type name 'FooBar'; did you mean 'Foobar'?}} +fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{no type named 'FooBar' in namespace 'fizbin'; did you mean 'Foobar'?}} namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}} int Double(int x) { return x + x; } void empty() { - Double(toFoobar()); // expected-error{{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}} + Double(toFoobar()); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}} } namespace fizbin { @@ -36,7 +36,7 @@ void Check() { // expected-note{{'Check' declared here}} } void Alt() { - Cleck(); // expected-error{{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}} + Cleck(); // expected-error{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}} } namespace N { @@ -64,13 +64,58 @@ void f() { // Test case from http://llvm.org/bugs/show_bug.cgi?id=10318 namespace llvm { - template <typename T> class GraphWriter {}; // expected-note {{'llvm::GraphWriter' declared here}} \ - // expected-note {{'GraphWriter' declared here}} + template <typename T> class GraphWriter {}; // expected-note 3{{declared here}} } struct S {}; void bar() { GraphWriter<S> x; //expected-error{{no template named 'GraphWriter'; did you mean 'llvm::GraphWriter'?}} - (void)new llvm::GraphWriter; // expected-error {{expected a type}} + (void)new llvm::GraphWriter; // expected-error {{use of class template llvm::GraphWriter requires template arguments}} (void)new llvm::Graphwriter<S>; // expected-error {{no template named 'Graphwriter' in namespace 'llvm'; did you mean 'GraphWriter'?}} } + +// If namespace prefixes and character edits have the same weight, correcting +// "fimish" to "N::famish" would have the same edit distance as correcting +// "fimish" to "Finish". The result would be no correction being suggested +// unless one of the corrections is given precedence (e.g. by filtering out +// suggestions with added namespace qualifiers). +namespace N { void famish(int); } +void Finish(int); // expected-note {{'Finish' declared here}} +void Start() { + fimish(7); // expected-error {{use of undeclared identifier 'fimish'; did you mean 'Finish'?}} +} + +// But just eliminating the corrections containing added namespace qualifiers +// won't work if both of the tied corrections have namespace qualifiers added. +namespace N { +void someCheck(int); // expected-note {{'N::someCheck' declared here}} +namespace O { void somechock(int); } +} +void confusing() { + somechick(7); // expected-error {{use of undeclared identifier 'somechick'; did you mean 'N::someCheck'?}} +} + + +class Message {}; +namespace extra { + namespace util { + namespace MessageUtils { + bool Equivalent(const Message&, const Message&); // expected-note {{'extra::util::MessageUtils::Equivalent' declared here}} \ + // expected-note {{'::extra::util::MessageUtils::Equivalent' declared here}} + } + } +} +namespace util { namespace MessageUtils {} } +bool nstest () { + Message a, b; + return util::MessageUtils::Equivalent(a, b); // expected-error {{no member named 'Equivalent' in namespace 'util::MessageUtils'; did you mean 'extra::util::MessageUtils::Equivalent'?}} +} + +namespace util { + namespace extra { + bool nstest () { + Message a, b; + return MessageUtils::Equivalent(a, b); // expected-error {{no member named 'Equivalent' in namespace 'util::MessageUtils'; did you mean '::extra::util::MessageUtils::Equivalent'?}} + } + } +} diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp index 52cae2e..e18b58b 100644 --- a/test/SemaCXX/namespace-alias.cpp +++ b/test/SemaCXX/namespace-alias.cpp @@ -11,9 +11,13 @@ 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 D = +i; // expected-error {{expected namespace name}} -namespace E = N::Foo; // expected-error {{expected namespace name}} +namespace E1 = N:: +Foo; // expected-error {{expected namespace name}} +namespace E2 = N:: +X; // expected-error {{expected namespace name}} namespace F { namespace A { namespace B { } } // expected-note {{candidate found by name lookup is 'F::A::B'}} diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index e13030c..b317634 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -45,7 +45,7 @@ void C2::m() { } namespace B { - void ::A::Af() {} // expected-error {{definition or redeclaration of 'Af' not in a namespace enclosing 'A'}} + void ::A::Af() {} // expected-error {{cannot define or redeclare 'Af' here because namespace 'B' does not enclose namespace 'A'}} } void f1() { @@ -160,7 +160,7 @@ namespace N { 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 ::global_func2(int) { } // expected-warning{{extra qualification on member 'global_func2'}} void N::f() { } // okay @@ -274,7 +274,8 @@ struct A { protected: struct B; struct B::C; // expected-error {{requires a template parameter list}} \ - // expected-error {{no struct named 'C'}} + // expected-error {{no struct named 'C'}} \ + // expected-error{{non-friend class member 'C' cannot have a qualified name}} }; template<typename T> diff --git a/test/SemaCXX/new-delete-0x.cpp b/test/SemaCXX/new-delete-0x.cpp new file mode 100644 index 0000000..dcc2e9b --- /dev/null +++ b/test/SemaCXX/new-delete-0x.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu -std=c++11 + +using size_t = decltype(sizeof(0)); +struct noreturn_t {} constexpr noreturn = {}; + +void *operator new [[noreturn]] (size_t, noreturn_t); +void operator delete [[noreturn]] (void*, noreturn_t); + +void good_news() +{ + auto p = new int[2][[]]; + auto q = new int[[]][2]; + auto r = new int*[[]][2][[]]; + auto s = new (int(*[[]])[2][[]]); +} + +void bad_news(int *ip) +{ + // attribute-specifiers can go almost anywhere in a new-type-id... + auto r = new int[[]{return 1;}()][2]; // expected-error {{expected ']'}} + auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected ']'}} + // ... but not here: + auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot appear here}} + auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} expected-error {{variably modified type}} +} + +void good_deletes() +{ + delete [&]{ return (int*)0; }(); + // FIXME: This appears to be legal. + delete []{ return (int*)0; }(); // unexpected-error {{expected expression}} +} diff --git a/test/SemaCXX/new-delete-cxx0x.cpp b/test/SemaCXX/new-delete-cxx0x.cpp new file mode 100644 index 0000000..c404fab --- /dev/null +++ b/test/SemaCXX/new-delete-cxx0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=i686-pc-linux-gnu + +void ugly_news(int *ip) { + // These are ill-formed according to one reading of C++98, and at the least + // have undefined behavior. But they're well-formed, and defined to throw + // std::bad_array_new_length, in C++11. + (void)new int[-1]; // expected-warning {{array size is negative}} + (void)new int[2000000000]; // expected-warning {{array is too large}} +} + + +struct S { + S(int); + S(); + ~S(); +}; + +struct T { // expected-note 2 {{not viable}} + T(int); // expected-note {{not viable}} +}; + +void fn() { + (void) new int[2] {1, 2}; + (void) new S[2] {1, 2}; + (void) new T[2] {1, 2}; // expected-error {{no matching constructor}} +} diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 748ce77..e77e3d6 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu #include <stddef.h> @@ -61,13 +61,13 @@ struct abstract { void bad_news(int *ip) { - int i = 1; + int i = 1; // expected-note 2{{here}} (void)new; // expected-error {{expected a type}} (void)new 4; // expected-error {{expected a type}} (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[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}} + (void)new int[1][i]; // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} + (void)new (int[1][i]); // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} (void)new (int[i]); // expected-warning {{when type is in parentheses}} (void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}} (void)new int(1, 2); // expected-error {{excess elements in scalar initializer}} @@ -77,7 +77,8 @@ void bad_news(int *ip) (void)new float*(ip); // expected-error {{cannot initialize a new value of type 'float *' with an lvalue of type 'int *'}} // 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 'S'}} + (void)new int[2000000000]; // expected-error {{array is too large}} + (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumeration type, not '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}} @@ -101,8 +102,7 @@ void good_deletes() 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 [0] (int*)0; // expected-error {{expected expression}} delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}} delete (T*)0; // expected-warning {{deleting pointer to incomplete type}} ::S::delete (int*)0; // expected-error {{expected unqualified-id}} @@ -386,7 +386,7 @@ namespace PairedDelete { namespace PR7702 { void test1() { - new DoesNotExist; // expected-error {{expected a type}} + new DoesNotExist; // expected-error {{unknown type name 'DoesNotExist'}} } } @@ -416,3 +416,86 @@ namespace PR10504 { }; void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}} } + +struct PlacementArg {}; +inline void *operator new[](size_t, const PlacementArg &) throw () { + return 0; +} +inline void operator delete[](void *, const PlacementArg &) throw () { +} + +namespace r150682 { + + template <typename X> + struct S { + struct Inner {}; + S() { new Inner[1]; } + }; + + struct T { + }; + + template<typename X> + void tfn() { + new (*(PlacementArg*)0) T[1]; + } + + void fn() { + tfn<int>(); + } + +} + +namespace P12023 { + struct CopyCounter + { + CopyCounter(); + CopyCounter(const CopyCounter&); + }; + + int main() + { + CopyCounter* f = new CopyCounter[10](CopyCounter()); // expected-error {{cannot have initialization arguments}} + return 0; + } +} + +namespace PR12061 { + template <class C> struct scoped_array { + scoped_array(C* p = __null); + }; + template <class Payload> struct Foo { + Foo() : a_(new scoped_array<int>[5]) { } + scoped_array< scoped_array<int> > a_; + }; + class Bar {}; + Foo<Bar> x; + + template <class C> struct scoped_array2 { + scoped_array2(C* p = __null, C* q = __null); + }; + template <class Payload> struct Foo2 { + Foo2() : a_(new scoped_array2<int>[5]) { } + scoped_array2< scoped_array2<int> > a_; + }; + class Bar2 {}; + Foo2<Bar2> x2; + + class MessageLoop { + public: + explicit MessageLoop(int type = 0); + }; + template <class CookieStoreTestTraits> + class CookieStoreTest { + protected: + CookieStoreTest() { + new MessageLoop; + } + }; + struct CookieMonsterTestTraits { + }; + class DeferredCookieTaskTest : public CookieStoreTest<CookieMonsterTestTraits> + { + DeferredCookieTaskTest() {} + }; +} diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp index 24590ce..a6c0dbf 100644 --- a/test/SemaCXX/null_in_arithmetic_ops.cpp +++ b/test/SemaCXX/null_in_arithmetic_ops.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify -Wno-string-plus-int %s #include <stddef.h> void f() { diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index 6f66036..e313603 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -109,19 +109,30 @@ namespace test3 { } } -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 +static_assert(__is_scalar(nullptr_t), ""); +static_assert(__is_pod(nullptr_t), ""); +static_assert(sizeof(nullptr_t) == sizeof(void*), ""); + +static_assert(!(nullptr < nullptr), ""); +static_assert(!(nullptr > nullptr), ""); +static_assert( nullptr <= nullptr, ""); +static_assert( nullptr >= nullptr, ""); +static_assert( nullptr == nullptr, ""); +static_assert(!(nullptr != nullptr), ""); + +static_assert(!(0 < nullptr), ""); +static_assert(!(0 > nullptr), ""); +static_assert( 0 <= nullptr, ""); +static_assert( 0 >= nullptr, ""); +static_assert( 0 == nullptr, ""); +static_assert(!(0 != nullptr), ""); + +static_assert(!(nullptr < 0), ""); +static_assert(!(nullptr > 0), ""); +static_assert( nullptr <= 0, ""); +static_assert( nullptr >= 0, ""); +static_assert( nullptr == 0, ""); +static_assert(!(nullptr != 0), ""); namespace overloading { int &f1(int*); @@ -161,3 +172,14 @@ namespace templates { X2<nullptr, nullptr, nullptr, nullptr> x2; } + +namespace null_pointer_constant { + +// Pending implementation of core issue 903, ensure we don't allow any of the +// C++11 constant evaluation semantics in null pointer constants. +struct S { int n; }; +constexpr int null() { return 0; } +void *p = S().n; // expected-error {{cannot initialize}} +void *q = null(); // expected-error {{cannot initialize}} + +} diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp index 17cee62..a5f5d34 100644 --- a/test/SemaCXX/offsetof.cpp +++ b/test/SemaCXX/offsetof.cpp @@ -66,3 +66,10 @@ struct bar : public foo { }; int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1]; + +struct LtoRCheck { + int a[10]; + int f(); +}; +int ltor = __builtin_offsetof(struct LtoRCheck, a[LtoRCheck().f]); // \ + expected-error {{reference to non-static member function must be called}} diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 00f6a94..b5e1214 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -8,10 +8,10 @@ void test_f(int iv, float 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 }} +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) { @@ -21,7 +21,7 @@ void test_g(int iv, float 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* dp2 = g(0, fv, 1.5); // expected-error {{call to 'g' is ambiguous}} } double* h(double f); @@ -126,9 +126,9 @@ void test_bitfield(Bits bits, int x) { 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 }} +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); @@ -137,7 +137,7 @@ void test_multiparm(long lv, short sv, int 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: }} + multiparm(sv, sv, lv); // expected-error {{call to 'multiparm' is ambiguous}} } // Test overloading based on qualification vs. no qualification @@ -183,9 +183,9 @@ void test_quals_ranking(int * p, int volatile *pq, int * * pp, int * * * ppp) { float* q6 = quals_rank2(pp); - quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}} + quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous}} - quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}} + quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous}} quals_rank3(pq); } @@ -233,7 +233,7 @@ float* intref(const int&); void intref_test() { float* ir1 = intref(5); - float* ir2 = intref(5.5); + float* ir2 = intref(5.5); // expected-warning{{implicit conversion turns literal floating-point number into integer}} } void derived5(C&); // expected-note{{candidate function not viable: cannot bind base class object of type 'A' to derived class reference 'C &' for 1st argument}} @@ -266,8 +266,8 @@ float& cvqual_subsume2(const volatile Y&); // expected-note{{candidate function} 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()); // expected-error{{call to 'cvqual_subsume2' is ambiguous; candidates are:}} + cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous}} + int& x = cvqual_subsume2(get_Z()); // expected-error{{call to 'cvqual_subsume2' is ambiguous}} } // Test overloading with cv-qualification differences in reference @@ -534,3 +534,37 @@ namespace rdar9803316 { int &ir = (&foo)(0); } } + +namespace IncompleteArg { + // Ensure that overload resolution attempts to complete argument types when + // performing ADL. + template<typename T> struct S { + friend int f(const S&); + }; + extern S<int> s; + int k = f(s); + + template<typename T> struct Op { + friend bool operator==(const Op &, const Op &); + }; + extern Op<char> op; + bool b = op == op; + + // ... and not in other cases! Nothing here requires U<int()> to be complete. + // (Note that instantiating U<int()> will fail.) + template<typename T> struct U { + T t; + }; + struct Consumer { + template<typename T> + int operator()(const U<T> &); + }; + template<typename T> U<T> &make(); + Consumer c; + int n = sizeof(c(make<int()>())); +} + +namespace PR12142 { + void fun(int (*x)[10]); // expected-note{{candidate function not viable: 1st argument ('const int (*)[10]') would lose const qualifier}} + void g() { fun((const int(*)[10])0); } // expected-error{{no matching function for call to 'fun'}} +} diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp index 37815b9..37c9552 100644 --- a/test/SemaCXX/overload-member-call.cpp +++ b/test/SemaCXX/overload-member-call.cpp @@ -32,7 +32,7 @@ struct X { static void test_member_static() { double& d1 = g(0.0); - g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}} + g(0); // expected-error{{call to 'g' is ambiguous}} } }; @@ -41,8 +41,8 @@ void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp) 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:}} + xv.f(0); // expected-error{{no matching member function for call to 'f'}} + xvp->f(0); // expected-error{{no matching member function for call to 'f'}} int& i3 = xc.g(0); int& i4 = xcp->g(0); @@ -50,7 +50,7 @@ void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp) 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::g(0); // expected-error{{call to 'g' is ambiguous}} X::h(0); // expected-error{{call to non-static member function without an object argument}} } diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp index a5ec51c..6da0354 100644 --- a/test/SemaCXX/overloaded-name.cpp +++ b/test/SemaCXX/overloaded-name.cpp @@ -21,11 +21,10 @@ namespace rdar9623945 { public: const char* text(void); void g(void) { - // FIXME: why 2x? f(text()); - f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}} + f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}} f(text()); - f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}} + f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}} } }; } diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 1e4a3b7..8ecb54d 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -232,7 +232,7 @@ struct Arrow2 { 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}} + a3->m; // expected-error{{no viable overloaded 'operator->'}} } struct CopyConBase { @@ -392,7 +392,7 @@ namespace rdar9136502 { }; struct Y { - Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}} + Y &operator<<(int); }; void f(X x, Y y) { @@ -408,3 +408,10 @@ class StringRef { }; } + +namespace PR11784 { + struct A { A& operator=(void (*x)()); }; + void f(); + void f(int); + void g() { A x; x = f; } +} diff --git a/test/SemaCXX/pragma-visibility.cpp b/test/SemaCXX/pragma-visibility.cpp new file mode 100644 index 0000000..e3ef97a --- /dev/null +++ b/test/SemaCXX/pragma-visibility.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test1 __attribute__((visibility("hidden"))) { // expected-note{{surrounding namespace with visibility attribute starts here}} +#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}} +} + +// GCC 4.6 accepts this, but the "hidden" leaks past the namespace end. +namespace test2 __attribute__((visibility("hidden"))) { +#pragma GCC visibility push(protected) // expected-error{{#pragma visibility push with no matching #pragma visibility pop}} +} // expected-note{{surrounding namespace with visibility attribute ends here}} + +#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}} + +// <rdar://problem/10871094> +struct A { + #pragma GCC visibility push(protected) + #pragma GCC visibility pop +}; + +void f() { + #pragma GCC visibility push(protected) + #pragma GCC visibility pop +} diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp index d71304e..a8f6683 100644 --- a/test/SemaCXX/pseudo-destructors.cpp +++ b/test/SemaCXX/pseudo-destructors.cpp @@ -19,7 +19,7 @@ void cv_test(const volatile T* cvt) { cvt->T::~T(); // no-warning } -void f(A* a, Foo *f, int *i, double *d) { +void f(A* a, Foo *f, int *i, double *d, int ii) { a->~A(); a->A::~A(); @@ -46,6 +46,9 @@ void f(A* a, Foo *f, int *i, double *d) { i->N::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}} i->Integer::~Double(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('Double' (aka 'double')) in pseudo-destructor expression}} + ii->~Integer(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} + ii.~Integer(); + cv_test(a); cv_test(f); cv_test(i); @@ -68,3 +71,12 @@ void test_X0(N1::X0 &x0) { x0.~X0(); } +namespace PR11339 { + template<class T> + void destroy(T* p) { + p->~T(); // ok + p->~oops(); // expected-error{{expected the class name after '~' to name a destructor}} + } + + template void destroy(int*); // expected-note{{in instantiation of function template specialization}} +} diff --git a/test/SemaCXX/qual-id-test.cpp b/test/SemaCXX/qual-id-test.cpp index e5c7306..9994d75 100644 --- a/test/SemaCXX/qual-id-test.cpp +++ b/test/SemaCXX/qual-id-test.cpp @@ -137,13 +137,13 @@ struct a { a a; -int a::sa = a.a; // expected-error {{invalid use of nonstatic data member 'a'}} +int a::sa = a.a; // expected-error {{invalid use of non-static data member 'a'}} namespace PR6645 { typedef int foo; namespace Inner { typedef int PR6645::foo; // expected-error{{typedef declarator cannot be qualified}} \ - // expected-error{{definition or redeclaration of 'foo' not in a namespace enclosing 'PR6645'}} + // expected-error{{cannot define or redeclare 'foo' here because namespace 'Inner' does not enclose namespace 'PR6645'}} } } diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index 3cd6e18..d65a468 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -146,3 +146,8 @@ namespace PR6830 { Z(foo::X()).Work(); } } + +namespace pr12339 { + extern "C" void i; + pr12339::FOO // expected-error{{no type named 'FOO' in namespace 'pr12339'}} +} // expected-error{{expected unqualified-id}} diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index 68005a5..7f41b93 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -9,13 +9,27 @@ typedef void (*fnptr)(); // Test the conversion to self. void self_conversion() { - // T*->T* is allowed, T->T in general not. + // T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't + // cast away constness, and is integral, enumeration, pointer or + // pointer-to-member. 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 'structure' to 'structure' is not allowed}} + (void)reinterpret_cast<int>(i); + + test e = testval; + (void)reinterpret_cast<test>(e); + + // T*->T* is allowed int *pi = 0; (void)reinterpret_cast<int*>(pi); + + const int structure::*psi = 0; + (void)reinterpret_cast<const int structure::*>(psi); + + structure s; + (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}} + + float f = 0.0f; + (void)reinterpret_cast<float>(f); // expected-error {{reinterpret_cast from 'float' to 'float' is not allowed}} } // Test conversion between pointer and integral types, as in /3 and /4. diff --git a/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp index 09d08f9..9cdf5a1 100644 --- a/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp +++ b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp @@ -4,6 +4,6 @@ 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}} + void *vp = reinterpret_cast<void*>(fp); // expected-warning {{cast between pointer-to-function and pointer-to-object is an extension}} + (void)reinterpret_cast<fnptr>(vp); // expected-warning {{cast between pointer-to-function and pointer-to-object is an extension}} } diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp index e06ba40..617de00 100644 --- a/test/SemaCXX/return-noreturn.cpp +++ b/test/SemaCXX/return-noreturn.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default +// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default // A destructor may be marked noreturn and should still influence the CFG. void pr6884_abort() __attribute__((noreturn)); diff --git a/test/SemaCXX/runtimediag-ppe.cpp b/test/SemaCXX/runtimediag-ppe.cpp new file mode 100644 index 0000000..0e8451b --- /dev/null +++ b/test/SemaCXX/runtimediag-ppe.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Make sure diagnostics that we don't print based on runtime control +// flow are delayed correctly in cases where we can't immediately tell whether +// the context is unevaluated. + +namespace std { + class type_info; +} + +int& NP(int); +void test1() { (void)typeid(NP(1 << 32)); } + +class Poly { virtual ~Poly(); }; +Poly& P(int); +void test2() { (void)typeid(P(1 << 32)); } // expected-warning {{shift count >= width of type}} + +void test3() { 1 ? (void)0 : (void)typeid(P(1 << 32)); } diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index ad109f4..b659de0 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -20,7 +20,7 @@ namespace test1 { int f(bool b) { if (b) - goto foo; // expected-error {{illegal goto into protected scope}} + goto foo; // expected-error {{goto into protected scope}} C c; // expected-note {{jump bypasses variable initialization}} foo: return 1; diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp index 0e27f46..6d04c84 100644 --- a/test/SemaCXX/statements.cpp +++ b/test/SemaCXX/statements.cpp @@ -10,7 +10,7 @@ struct X { }; void test2() { - goto later; // expected-error {{illegal goto into protected scope}} + goto later; // expected-error {{goto into protected scope}} X x; // expected-note {{jump bypasses variable initialization}} later: ; diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp index 0991a5f..364e4e4 100644 --- a/test/SemaCXX/static-assert.cpp +++ b/test/SemaCXX/static-assert.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=x86_64-linux-gnu -int f(); +int f(); // expected-note {{declared here}} -static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}} +static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} static_assert(true, "true is not false"); static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} @@ -28,3 +28,9 @@ template<typename T> struct S { S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}} S<int> s2; +static_assert(false, L"\xFFFFFFFF"); // expected-error {{static_assert failed L"\xFFFFFFFF"}} +static_assert(false, u"\U000317FF"); // expected-error {{static_assert failed u"\U000317FF"}} +// FIXME: render this as u8"\u03A9" +static_assert(false, u8"Ω"); // expected-error {{static_assert failed u8"\316\251"}} +static_assert(false, L"\u1234"); // expected-error {{static_assert failed L"\x1234"}} +static_assert(false, L"\x1ff" "0\x123" "fx\xfffff" "goop"); // expected-error {{static_assert failed L"\x1FF""0\x123""fx\xFFFFFgoop"}} diff --git a/test/SemaCXX/string-plus-int.cpp b/test/SemaCXX/string-plus-int.cpp new file mode 100644 index 0000000..5752f8f --- /dev/null +++ b/test/SemaCXX/string-plus-int.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-array-bounds %s -fpascal-strings +// RUN: %clang_cc1 -fdiagnostics-parseable-fixits -x c++ %s 2>&1 -Wno-array-bounds -fpascal-strings | FileCheck %s + +void consume(const char* c) {} +void consume(const unsigned char* c) {} +void consume(const wchar_t* c) {} +void consumeChar(char c) {} + +enum MyEnum { + kMySmallEnum = 1, + kMyEnum = 5 +}; + +enum OperatorOverloadEnum { + kMyOperatorOverloadedEnum = 5 +}; + +const char* operator+(const char* c, OperatorOverloadEnum e) { + return "yo"; +} + +const char* operator+(OperatorOverloadEnum e, const char* c) { + return "yo"; +} + +void f(int index) { + // Should warn. + // CHECK: fix-it:"{{.*}}":{31:11-31:11}:"&" + // CHECK: fix-it:"{{.*}}":{31:17-31:18}:"[" + // CHECK: fix-it:"{{.*}}":{31:20-31:20}:"]" + consume("foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume("foo" + index); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume("foo" + kMyEnum); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + + consume(5 + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume(index + "foo"); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consume(kMyEnum + "foo"); // expected-warning {{adding 'MyEnum' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + + // FIXME: suggest replacing with "foo"[5] + consumeChar(*("foo" + 5)); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + consumeChar(*(5 + "foo")); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + + consume(L"foo" + 5); // expected-warning {{adding 'int' to a string does not append to the string}} expected-note {{use array indexing to silence this warning}} + + // Should not warn. + consume(&("foo"[3])); + consume(&("foo"[index])); + consume(&("foo"[kMyEnum])); + consume("foo" + kMySmallEnum); + consume(kMySmallEnum + "foo"); + + consume(L"foo" + 2); + + consume("foo" + 3); // Points at the \0 + consume("foo" + 4); // Points 1 past the \0, which is legal too. + consume("\pfoo" + 4); // Pascal strings don't have a trailing \0, but they + // have a leading length byte, so this is fine too. + + consume("foo" + kMyOperatorOverloadedEnum); + consume(kMyOperatorOverloadedEnum + "foo"); + + #define A "foo" + #define B "bar" + consume(A B + sizeof(A) - 1); +} + diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp index 8a8cf33..517faa9 100644 --- a/test/SemaCXX/switch.cpp +++ b/test/SemaCXX/switch.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-enum %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s void test() { bool x = true; @@ -64,3 +64,24 @@ void click_check_header_sizes() { case 0: ; } } + +void local_class(int n) { + for (;;) switch (n) { + case 0: + struct S { + void f() { + case 1: // expected-error {{'case' statement not in switch statement}} + break; // expected-error {{'break' statement not in loop or switch statement}} + default: // expected-error {{'default' statement not in switch statement}} + continue; // expected-error {{'continue' statement not in loop statement}} + } + }; + S().f(); + []{ + case 2: // expected-error {{'case' statement not in switch statement}} + break; // expected-error {{'break' statement not in loop or switch statement}} + default: // expected-error {{'default' statement not in switch statement}} + continue; // expected-error {{'continue' statement not in loop statement}} + }(); + } +} diff --git a/test/SemaCXX/this.cpp b/test/SemaCXX/this.cpp index 167755f..27ee1e8 100644 --- a/test/SemaCXX/this.cpp +++ b/test/SemaCXX/this.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} +int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}} void f() { - int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} + int x = this; // expected-error {{invalid use of 'this' outside of a non-static member function}} } diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp index e25939f..c219b77 100644 --- a/test/SemaCXX/trailing-return-0x.cpp +++ b/test/SemaCXX/trailing-return-0x.cpp @@ -21,6 +21,16 @@ auto g(); // expected-error{{return without trailing return type}} int h() -> int; // expected-error{{trailing return type must specify return type 'auto', not 'int'}} +int i(); +auto i() -> int; +int i() {} + +using T = auto (int) -> auto (*)(char) -> void; // expected-note {{previous}} +using T = void; // expected-error {{type alias redefinition with different types ('void' vs 'auto (int) -> auto (*)(char) -> void')}} + +using U = auto (int) -> auto (*)(char) -> void; +using U = void (*(int))(char); // ok + int x; template <class T> diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 0914c7c..f53939a 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -39,6 +39,18 @@ struct DerivesEmpty : Empty {}; struct HasCons { HasCons(int); }; struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); }; struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; +struct HasDefaultTrivialCopyAssign { + HasDefaultTrivialCopyAssign &operator =(const HasDefaultTrivialCopyAssign&) + = default; +}; +struct TrivialMoveButNotCopy { + TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default; + TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&); +}; +struct NonTrivialDefault { + NonTrivialDefault(); +}; + struct HasDest { ~HasDest(); }; class HasPriv { int priv; }; class HasProt { protected: int prot; }; @@ -96,6 +108,10 @@ class AllPrivate { ~AllPrivate() throw(); }; +struct ThreeArgCtor { + ThreeArgCtor(int*, char*, int); +}; + void is_pod() { { int arr[T(__is_pod(int))]; } @@ -235,6 +251,37 @@ void is_enum() { int arr[F(__is_enum(HasAnonymousUnion))]; } } +struct FinalClass final { +}; + +template<typename T> +struct PotentiallyFinal { }; + +template<typename T> +struct PotentiallyFinal<T*> final { }; + +template<> +struct PotentiallyFinal<int> final { }; + +void is_final() +{ + { int arr[T(__is_final(FinalClass))]; } + { int arr[T(__is_final(PotentiallyFinal<float*>))]; } + { int arr[T(__is_final(PotentiallyFinal<int>))]; } + + { int arr[F(__is_final(int))]; } + { int arr[F(__is_final(Union))]; } + { int arr[F(__is_final(Int))]; } + { int arr[F(__is_final(IntAr))]; } + { int arr[F(__is_final(UnionAr))]; } + { int arr[F(__is_final(Derives))]; } + { int arr[F(__is_final(ClassType))]; } + { int arr[F(__is_final(cvoid))]; } + { int arr[F(__is_final(IntArNB))]; } + { int arr[F(__is_final(HasAnonymousUnion))]; } + { int arr[F(__is_final(PotentiallyFinal<float>))]; } +} + typedef HasVirt Polymorph; struct InheritPolymorph : Polymorph {}; @@ -885,6 +932,41 @@ struct NonTCStruct { NonTCStruct(const NonTCStruct&) {} }; +struct AllDefaulted { + AllDefaulted() = default; + AllDefaulted(const AllDefaulted &) = default; + AllDefaulted(AllDefaulted &&) = default; + AllDefaulted &operator=(const AllDefaulted &) = default; + AllDefaulted &operator=(AllDefaulted &&) = default; + ~AllDefaulted() = default; +}; + +struct AllDeleted { + AllDeleted() = delete; + AllDeleted(const AllDeleted &) = delete; + AllDeleted(AllDeleted &&) = delete; + AllDeleted &operator=(const AllDeleted &) = delete; + AllDeleted &operator=(AllDeleted &&) = delete; + ~AllDeleted() = delete; +}; + +struct ExtDefaulted { + ExtDefaulted(); + ExtDefaulted(const ExtDefaulted &); + ExtDefaulted(ExtDefaulted &&); + ExtDefaulted &operator=(const ExtDefaulted &); + ExtDefaulted &operator=(ExtDefaulted &&); + ~ExtDefaulted(); +}; + +// Despite being defaulted, these functions are not trivial. +ExtDefaulted::ExtDefaulted() = default; +ExtDefaulted::ExtDefaulted(const ExtDefaulted &) = default; +ExtDefaulted::ExtDefaulted(ExtDefaulted &&) = default; +ExtDefaulted &ExtDefaulted::operator=(const ExtDefaulted &) = default; +ExtDefaulted &ExtDefaulted::operator=(ExtDefaulted &&) = default; +ExtDefaulted::~ExtDefaulted() = default; + void is_trivial2() { int t01[T(__is_trivial(char))]; @@ -909,11 +991,14 @@ void is_trivial2() int t20[T(__is_trivial(Union))]; int t21[T(__is_trivial(UnionAr))]; int t22[T(__is_trivial(TrivialStruct))]; + int t23[T(__is_trivial(AllDefaulted))]; + int t24[T(__is_trivial(AllDeleted))]; int t30[F(__is_trivial(void))]; int t31[F(__is_trivial(NonTrivialStruct))]; int t32[F(__is_trivial(SuperNonTrivialStruct))]; int t33[F(__is_trivial(NonTCStruct))]; + int t34[F(__is_trivial(ExtDefaulted))]; } void is_trivially_copyable2() @@ -941,10 +1026,13 @@ void is_trivially_copyable2() int t21[T(__is_trivially_copyable(UnionAr))]; int t22[T(__is_trivially_copyable(TrivialStruct))]; int t23[T(__is_trivially_copyable(NonTrivialStruct))]; + int t24[T(__is_trivially_copyable(AllDefaulted))]; + int t25[T(__is_trivially_copyable(AllDeleted))]; int t30[F(__is_trivially_copyable(void))]; - int t32[F(__is_trivially_copyable(SuperNonTrivialStruct))]; - int t31[F(__is_trivially_copyable(NonTCStruct))]; + int t31[F(__is_trivially_copyable(SuperNonTrivialStruct))]; + int t32[F(__is_trivially_copyable(NonTCStruct))]; + int t33[F(__is_trivially_copyable(ExtDefaulted))]; } struct CStruct { @@ -1100,6 +1188,8 @@ void has_trivial_default_constructor() { { int arr[T(__has_trivial_constructor(HasCopyAssign))]; } { int arr[T(__has_trivial_constructor(HasMoveAssign))]; } { int arr[T(__has_trivial_constructor(const Int))]; } + { int arr[T(__has_trivial_constructor(AllDefaulted))]; } + { int arr[T(__has_trivial_constructor(AllDeleted))]; } { int arr[F(__has_trivial_constructor(HasCons))]; } { int arr[F(__has_trivial_constructor(HasRef))]; } @@ -1110,6 +1200,7 @@ void has_trivial_default_constructor() { { int arr[F(__has_trivial_constructor(cvoid))]; } { int arr[F(__has_trivial_constructor(HasTemplateCons))]; } { int arr[F(__has_trivial_constructor(AllPrivate))]; } + { int arr[F(__has_trivial_constructor(ExtDefaulted))]; } } void has_trivial_copy_constructor() { @@ -1130,6 +1221,8 @@ void has_trivial_copy_constructor() { { int arr[T(__has_trivial_copy(HasCopyAssign))]; } { int arr[T(__has_trivial_copy(HasMoveAssign))]; } { int arr[T(__has_trivial_copy(const Int))]; } + { int arr[T(__has_trivial_copy(AllDefaulted))]; } + { int arr[T(__has_trivial_copy(AllDeleted))]; } { int arr[F(__has_trivial_copy(HasCopy))]; } { int arr[F(__has_trivial_copy(HasTemplateCons))]; } @@ -1138,6 +1231,7 @@ void has_trivial_copy_constructor() { { int arr[F(__has_trivial_copy(void))]; } { int arr[F(__has_trivial_copy(cvoid))]; } { int arr[F(__has_trivial_copy(AllPrivate))]; } + { int arr[F(__has_trivial_copy(ExtDefaulted))]; } } void has_trivial_copy_assignment() { @@ -1154,6 +1248,8 @@ void has_trivial_copy_assignment() { { int arr[T(__has_trivial_assign(HasCopy))]; } { int arr[T(__has_trivial_assign(HasMove))]; } { int arr[T(__has_trivial_assign(HasMoveAssign))]; } + { int arr[T(__has_trivial_assign(AllDefaulted))]; } + { int arr[T(__has_trivial_assign(AllDeleted))]; } { int arr[F(__has_trivial_assign(IntRef))]; } { int arr[F(__has_trivial_assign(HasCopyAssign))]; } @@ -1165,6 +1261,7 @@ void has_trivial_copy_assignment() { { int arr[F(__has_trivial_assign(void))]; } { int arr[F(__has_trivial_assign(cvoid))]; } { int arr[F(__has_trivial_assign(AllPrivate))]; } + { int arr[F(__has_trivial_assign(ExtDefaulted))]; } } void has_trivial_destructor() { @@ -1187,11 +1284,14 @@ void has_trivial_destructor() { { int arr[T(__has_trivial_destructor(const Int))]; } { int arr[T(__has_trivial_destructor(DerivesAr))]; } { int arr[T(__has_trivial_destructor(VirtAr))]; } + { int arr[T(__has_trivial_destructor(AllDefaulted))]; } + { int arr[T(__has_trivial_destructor(AllDeleted))]; } { int arr[F(__has_trivial_destructor(HasDest))]; } { int arr[F(__has_trivial_destructor(void))]; } { int arr[F(__has_trivial_destructor(cvoid))]; } { int arr[F(__has_trivial_destructor(AllPrivate))]; } + { int arr[F(__has_trivial_destructor(ExtDefaulted))]; } } struct A { ~A() {} }; @@ -1413,13 +1513,11 @@ void is_base_of() { isBaseOfF<DerivedB<int>, BaseA<int> >(); } -#if 0 template<class T, class U> class TemplateClass {}; template<class T> using TemplateAlias = TemplateClass<T, int>; -#endif typedef class Base BaseTypedef; @@ -1427,9 +1525,7 @@ void is_same() { int t01[T(__is_same(Base, Base))]; int t02[T(__is_same(Base, BaseTypedef))]; -#if 0 int t03[T(__is_same(TemplateClass<int, int>, TemplateAlias<int>))]; -#endif int t10[F(__is_same(Base, const Base))]; int t11[F(__is_same(Base, Base&))]; @@ -1512,6 +1608,12 @@ void is_convertible_to() { { int arr[T(__is_convertible_to(X0<int>, X0<float>))]; } } +namespace is_convertible_to_instantiate { + // Make sure we don't try to instantiate the constructor. + template<int x> class A { A(int) { int a[x]; } }; + int x = __is_convertible_to(int, A<-1>); +} + void is_trivial() { { int arr[T(__is_trivial(int))]; } @@ -1557,7 +1659,7 @@ void is_trivial() { int arr[F(__is_trivial(cvoid))]; } } -void is_trivially_copyable() +void trivial_checks() { { int arr[T(__is_trivially_copyable(int))]; } { int arr[T(__is_trivially_copyable(Enum))]; } @@ -1600,6 +1702,108 @@ void is_trivially_copyable() { int arr[F(__is_trivially_copyable(DerivesHasVirt))]; } { int arr[F(__is_trivially_copyable(void))]; } { int arr[F(__is_trivially_copyable(cvoid))]; } + + { int arr[T((__is_trivially_constructible(int)))]; } + { int arr[T((__is_trivially_constructible(int, int)))]; } + { int arr[T((__is_trivially_constructible(int, float)))]; } + { int arr[T((__is_trivially_constructible(int, int&)))]; } + { int arr[T((__is_trivially_constructible(int, const int&)))]; } + { int arr[T((__is_trivially_constructible(int, int)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; } + { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; } + { int arr[T((__is_trivially_constructible(NonTrivialDefault, + const NonTrivialDefault&)))]; } + { int arr[T((__is_trivially_constructible(NonTrivialDefault, + NonTrivialDefault&&)))]; } + { int arr[T((__is_trivially_constructible(AllDefaulted)))]; } + { int arr[T((__is_trivially_constructible(AllDefaulted, + const AllDefaulted &)))]; } + { int arr[T((__is_trivially_constructible(AllDefaulted, + AllDefaulted &&)))]; } + + { int arr[F((__is_trivially_constructible(int, int*)))]; } + { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; } + { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; } + { int arr[F((__is_trivially_constructible(AllDeleted)))]; } + { int arr[F((__is_trivially_constructible(AllDeleted, + const AllDeleted &)))]; } + { int arr[F((__is_trivially_constructible(AllDeleted, + AllDeleted &&)))]; } + { int arr[F((__is_trivially_constructible(ExtDefaulted)))]; } + { int arr[F((__is_trivially_constructible(ExtDefaulted, + const ExtDefaulted &)))]; } + { int arr[F((__is_trivially_constructible(ExtDefaulted, + ExtDefaulted &&)))]; } + + { int arr[T((__is_trivially_assignable(int&, int)))]; } + { int arr[T((__is_trivially_assignable(int&, int&)))]; } + { int arr[T((__is_trivially_assignable(int&, int&&)))]; } + { int arr[T((__is_trivially_assignable(int&, const int&)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD&)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; } + { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; } + { int arr[T((__is_trivially_assignable(int*&, int*)))]; } + { int arr[T((__is_trivially_assignable(AllDefaulted, + const AllDefaulted &)))]; } + { int arr[T((__is_trivially_assignable(AllDefaulted, + AllDefaulted &&)))]; } + + { int arr[F((__is_trivially_assignable(int*&, float*)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, const HasCopyAssign&)))]; } + { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&&)))]; } + { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, + TrivialMoveButNotCopy&)))]; } + { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&, + const TrivialMoveButNotCopy&)))]; } + { int arr[F((__is_trivially_assignable(AllDeleted, + const AllDeleted &)))]; } + { int arr[F((__is_trivially_assignable(AllDeleted, + AllDeleted &&)))]; } + { int arr[F((__is_trivially_assignable(ExtDefaulted, + const ExtDefaulted &)))]; } + { int arr[F((__is_trivially_assignable(ExtDefaulted, + ExtDefaulted &&)))]; } + + { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&, + HasDefaultTrivialCopyAssign&)))]; } + { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&, + const HasDefaultTrivialCopyAssign&)))]; } + { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&, + TrivialMoveButNotCopy)))]; } + { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&, + TrivialMoveButNotCopy&&)))]; } +} + +// Instantiation of __is_trivially_constructible +template<typename T, typename ...Args> +struct is_trivially_constructible { + static const bool value = __is_trivially_constructible(T, Args...); +}; + +void is_trivially_constructible_test() { + { int arr[T((is_trivially_constructible<int>::value))]; } + { int arr[T((is_trivially_constructible<int, int>::value))]; } + { int arr[T((is_trivially_constructible<int, float>::value))]; } + { int arr[T((is_trivially_constructible<int, int&>::value))]; } + { int arr[T((is_trivially_constructible<int, const int&>::value))]; } + { int arr[T((is_trivially_constructible<int, int>::value))]; } + { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign>::value))]; } + { int arr[T((is_trivially_constructible<HasCopyAssign, const HasCopyAssign&>::value))]; } + { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign&&>::value))]; } + { int arr[T((is_trivially_constructible<HasCopyAssign>::value))]; } + { int arr[T((is_trivially_constructible<NonTrivialDefault, + const NonTrivialDefault&>::value))]; } + { int arr[T((is_trivially_constructible<NonTrivialDefault, + NonTrivialDefault&&>::value))]; } + + { int arr[F((is_trivially_constructible<int, int*>::value))]; } + { int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; } + { int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, int&>::value))]; } } void array_rank() { diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp index 7db1970..b53bcd2 100644 --- a/test/SemaCXX/typedef-redecl.cpp +++ b/test/SemaCXX/typedef-redecl.cpp @@ -54,3 +54,42 @@ namespace PR7462 { typedef int operator! (A); // expected-error{{typedef name must be an identifier}} int i = !A(); // expected-error{{invalid argument type}} } + +template<typename T> +typedef T f(T t) { return t; } // expected-error {{function definition declared 'typedef'}} +int k = f(0); +int k2 = k; + +namespace PR11630 { + template <class T> + struct S + { + static const unsigned C = 1; + static void f() + { + typedef int q[C == 1 ? 1 : -1]; // expected-note{{previous definition is here}} + typedef int q[C >= 1 ? 2 : -2]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}} + typedef int n[C == 1 ? 1 : -1]; + typedef int n[C >= 1 ? 1 : -1]; + } + }; + + template <int T> + struct S2 + { + static void f() + { + typedef int q[1]; // expected-note{{previous definition is here}} + typedef int q[T]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}} + } + }; + + void f() { + S<int> a; + a.f(); // expected-note{{in instantiation of member function 'PR11630::S<int>::f' requested here}} + S2<1> b; + b.f(); + S2<2> b2; + b2.f(); // expected-note{{in instantiation of member function 'PR11630::S2<2>::f' requested here}} + } +} diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp index 8db7db5..d3a2a28 100644 --- a/test/SemaCXX/typeid.cpp +++ b/test/SemaCXX/typeid.cpp @@ -2,7 +2,7 @@ void f() { - (void)typeid(int); // expected-error {{error: you need to include <typeinfo> before using the 'typeid' operator}} + (void)typeid(int); // expected-error {{you need to include <typeinfo> before using the 'typeid' operator}} } namespace std { diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index fa32c57..b1e8d91 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s struct errc { int v_; @@ -29,3 +29,164 @@ public: inline error_condition make_error_condition(errc _e) { return error_condition(static_cast<int>(_e)); } + + +// Prior to the introduction of a callback object to further filter possible +// typo corrections, this example would not trigger a suggestion as "base_type" +// is a closer match to "basetype" than is "BaseType" but "base_type" does not +// refer to a base class or non-static data member. +struct BaseType { }; +struct Derived : public BaseType { // expected-note {{base class 'BaseType' specified here}} + static int base_type; // expected-note {{'base_type' declared here}} + Derived() : basetype() {} // expected-error{{initializer 'basetype' does not name a non-static data member or base class; did you mean the base class 'BaseType'?}} +}; + +// Test the improvement from passing a callback object to CorrectTypo in +// the helper function LookupMemberExprInRecord. +int get_type(struct Derived *st) { + return st->Base_Type; // expected-error{{no member named 'Base_Type' in 'Derived'; did you mean 'base_type'?}} +} + +// In this example, somename should not be corrected to the cached correction +// "some_name" since "some_name" is a class and a namespace name is needed. +class some_name {}; // expected-note {{'some_name' declared here}} +somename Foo; // expected-error {{unknown type name 'somename'; did you mean 'some_name'?}} +namespace SomeName {} // expected-note {{namespace 'SomeName' defined here}} +using namespace somename; // expected-error {{no namespace named 'somename'; did you mean 'SomeName'?}} + + +// Without the callback object, CorrectTypo would choose "field1" as the +// correction for "fielda" as it is closer than "FieldA", but that correction +// would be later discarded by the caller and no suggestion would be given. +struct st { + struct { + int field1; + }; + double FieldA; // expected-note{{'FieldA' declared here}} +}; +st var = { .fielda = 0.0 }; // expected-error{{field designator 'fielda' does not refer to any field in type 'st'; did you mean 'FieldA'?}} + +// Test the improvement from passing a callback object to CorrectTypo in +// Sema::BuildCXXNestedNameSpecifier. And also for the improvement by doing +// so in Sema::getTypeName. +typedef char* another_str; // expected-note{{'another_str' declared here}} +namespace AnotherStd { // expected-note{{'AnotherStd' declared here}} + class string {}; +} +another_std::string str; // expected-error{{use of undeclared identifier 'another_std'; did you mean 'AnotherStd'?}} +another_str *cstr = new AnotherStr; // expected-error{{unknown type name 'AnotherStr'; did you mean 'another_str'?}} + +// Test the improvement from passing a callback object to CorrectTypo in +// Sema::ActOnSizeofParameterPackExpr. +char* TireNames; +template<typename ...TypeNames> struct count { // expected-note{{parameter pack 'TypeNames' declared here}} + static const unsigned value = sizeof...(TyreNames); // expected-error{{'TyreNames' does not refer to the name of a parameter pack; did you mean 'TypeNames'?}} +}; + +// Test the typo-correction callback in Sema::DiagnoseUnknownTypeName. +namespace unknown_type_test { + class StreamOut {}; // expected-note 2 {{'StreamOut' declared here}} + long stream_count; // expected-note 2 {{'stream_count' declared here}} +}; +unknown_type_test::stream_out out; // expected-error{{no type named 'stream_out' in namespace 'unknown_type_test'; did you mean 'StreamOut'?}} + +// Demonstrate a case where using only the cached value returns the wrong thing +// when the cached value was the result of a previous callback object that only +// accepts a subset of the current callback object. +namespace { +using namespace unknown_type_test; +void bar(long i); +void before_caching_classname() { + bar((stream_out)); // expected-error{{use of undeclared identifier 'stream_out'; did you mean 'stream_count'?}} +} +stream_out out; // expected-error{{unknown type name 'stream_out'; did you mean 'StreamOut'?}} +void after_caching_classname() { + bar((stream_out)); // expected-error{{use of undeclared identifier 'stream_out'; did you mean 'stream_count'?}} +} +} + +// Test the typo-correction callback in Sema::DiagnoseInvalidRedeclaration. +struct BaseDecl { + void add_in(int i); +}; +struct TestRedecl : public BaseDecl { + void add_it(int i); // expected-note{{'add_it' declared here}} +}; +void TestRedecl::add_in(int i) {} // expected-error{{out-of-line definition of 'add_in' does not match any declaration in 'TestRedecl'; did you mean 'add_it'?}} + +// Test the improved typo correction for the Parser::ParseCastExpr => +// Sema::ActOnIdExpression => Sema::DiagnoseEmptyLookup call path. +class SomeNetMessage; +class Message {}; +void foo(Message&); +void foo(SomeNetMessage&); +void doit(void *data) { + Message somenetmsg; // expected-note{{'somenetmsg' declared here}} + foo(somenetmessage); // expected-error{{use of undeclared identifier 'somenetmessage'; did you mean 'somenetmsg'?}} + foo((somenetmessage)data); // expected-error{{use of undeclared identifier 'somenetmessage'; did you mean 'SomeNetMessage'?}} +} + +// Test the typo-correction callback in BuildRecoveryCallExpr. +// Solves the main issue in PR 9320 of suggesting corrections that take the +// wrong number of arguments. +void revoke(const char*); // expected-note 2{{'revoke' declared here}} +void Test() { + Invoke(); // expected-error{{use of undeclared identifier 'Invoke'}} + Invoke("foo"); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'revoke'?}} + Invoke("foo", "bar"); // expected-error{{use of undeclared identifier 'Invoke'}} +} +void Test2(void (*invoke)(const char *, int)) { // expected-note{{'invoke' declared here}} + Invoke(); // expected-error{{use of undeclared identifier 'Invoke'}} + Invoke("foo"); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'revoke'?}} + Invoke("foo", 7); // expected-error{{use of undeclared identifier 'Invoke'; did you mean 'invoke'?}} + Invoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Invoke'}} +} + +void provoke(const char *x, bool y=false) {} // expected-note 2{{'provoke' declared here}} +void Test3() { + Provoke(); // expected-error{{use of undeclared identifier 'Provoke'}} + Provoke("foo"); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}} + Provoke("foo", true); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}} + Provoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Provoke'}} +} + +// PR 11737 - Don't try to typo-correct the implicit 'begin' and 'end' in a +// C++11 for-range statement. +struct R {}; +bool begun(R); +void RangeTest() { + for (auto b : R()) {} // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type}} +} + +// PR 12019 - Avoid infinite mutual recursion in DiagnoseInvalidRedeclaration +// by not trying to typo-correct a method redeclaration to declarations not +// in the current record. +class Parent { + void set_types(int index, int value); + void add_types(int value); +}; +class Child: public Parent {}; +void Child::add_types(int value) {} // expected-error{{out-of-line definition of 'add_types' does not match any declaration in 'Child'}} + +// Fix the callback based filtering of typo corrections within +// Sema::ActOnIdExpression by Parser::ParseCastExpression to allow type names as +// potential corrections for template arguments. +namespace clash { +class ConstructExpr {}; // expected-note{{'clash::ConstructExpr' declared here}} +} +class ClashTool { + bool HaveConstructExpr(); + template <class T> T* getExprAs(); + + void test() { + ConstructExpr *expr = // expected-error{{unknown type name 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}} + getExprAs<ConstructExpr>(); // expected-error{{use of undeclared identifier 'ConstructExpr'; did you mean 'clash::ConstructExpr'?}} + } +}; + +namespace test1 { + struct S { + struct Foobar *f; // expected-note{{'Foobar' declared here}} + }; + test1::FooBar *b; // expected-error{{no type named 'FooBar' in namespace 'test1'; did you mean 'Foobar'?}} +} diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp index e926f18..1541720 100644 --- a/test/SemaCXX/undefined-internal.cpp +++ b/test/SemaCXX/undefined-internal.cpp @@ -122,3 +122,62 @@ namespace PR9323 { f(Uncopyable()); // expected-warning {{C++98 requires an accessible copy constructor}} }; } + + +namespace std { class type_info; }; +namespace cxx11_odr_rules { + // Note: the way this test is written isn't really ideal, but there really + // isn't any other way to check that the odr-used logic for constants + // is working without working implicit capture in lambda-expressions. + // (The more accurate used-but-not-defined warning is the only other visible + // effect of accurate odr-used computation.) + // + // Note that the warning in question can trigger in cases some people would + // consider false positives; hopefully that happens rarely in practice. + // + // FIXME: Suppressing this test while I figure out how to fix a bug in the + // odr-use marking code. + + namespace { + struct A { + static const int unused = 10; + static const int used1 = 20; // xpected-warning {{internal linkage}} + static const int used2 = 20; // xpected-warning {{internal linkage}} + virtual ~A() {} + }; + } + + void a(int,int); + A& p(const int&) { static A a; return a; } + + // Check handling of default arguments + void b(int = A::unused); + + void tests() { + // Basic test + a(A::unused, A::unused); + + // Check that nesting an unevaluated or constant-evaluated context does + // the right thing. + a(A::unused, sizeof(int[10])); + + // Check that the checks work with unevaluated contexts + (void)sizeof(p(A::used1)); + (void)typeid(p(A::used1)); // xpected-note {{used here}} + + // Misc other testing + a(A::unused, 1 ? A::used2 : A::used2); // xpected-note {{used here}} + b(); + } +} + + +namespace OverloadUse { + namespace { + void f(); + void f(int); // expected-warning {{function 'OverloadUse::<anonymous namespace>::f' has internal linkage but is not defined}} + } + template<void x()> void t(int*) { x(); } + template<void x(int)> void t(long*) { x(10); } // expected-note {{used here}} + void g() { long a; t<f>(&a); } +} diff --git a/test/SemaCXX/underlying_type.cpp b/test/SemaCXX/underlying_type.cpp index dcfaab3..7bca06b 100644 --- a/test/SemaCXX/underlying_type.cpp +++ b/test/SemaCXX/underlying_type.cpp @@ -35,3 +35,9 @@ 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}} + +using uint = unsigned; +enum class foo : uint { bar }; + +static_assert(is_same_type<underlying_type<foo>::type, unsigned>::value, + "foo has the wrong underlying type"); diff --git a/test/SemaCXX/uninit-variables.cpp b/test/SemaCXX/uninit-variables.cpp index 358a572..eb6428d 100644 --- a/test/SemaCXX/uninit-variables.cpp +++ b/test/SemaCXX/uninit-variables.cpp @@ -27,7 +27,7 @@ void unevaluated_tests() { struct A { virtual ~A() {} }; void polymorphic_test() { A *a; // expected-note{{initialize the variable 'a' to silence this warning}} - (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here }} + (void)typeid(*a); // expected-warning{{variable 'a' is uninitialized when used here}} } // Handle cases where the CFG may constant fold some branches, thus diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index c25bd20..7879e7c 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -std=c++11 -verify %s int foo(int x); int bar(int* x); @@ -33,6 +33,7 @@ class A { int num; static int count; int get() const { return num; } + int get2() { return num; } void set(int x) { num = x; } static int zero() { return 0; } @@ -41,6 +42,7 @@ class A { A(int x) {} A(int *x) {} A(A *a) {} + ~A(); }; A getA() { return A(); } @@ -66,6 +68,7 @@ void setupA() { A a14 = A(a14); // expected-warning {{variable 'a14' is uninitialized when used within its own initialization}} A a15 = getA(a15.num); // expected-warning {{variable 'a15' is uninitialized when used within its own initialization}} A a16(&a16.num); // expected-warning {{variable 'a16' is uninitialized when used within its own initialization}} + A a17(a17.get2()); // expected-warning {{variable 'a17' is uninitialized when used within its own initialization}} } struct B { @@ -117,3 +120,50 @@ struct S { }; struct C { char a[100], *e; } car = { .e = car.a }; + +// <rdar://problem/10398199> +namespace rdar10398199 { + class FooBase { protected: ~FooBase() {} }; + class Foo : public FooBase { + public: + operator int&() const; + }; + void stuff(); + template <typename T> class FooImpl : public Foo { + T val; + public: + FooImpl(const T &x) : val(x) {} + ~FooImpl() { stuff(); } + }; + + template <typename T> FooImpl<T> makeFoo(const T& x) { + return FooImpl<T>(x); + } + + void test() { + const Foo &x = makeFoo(42); + const int&y = makeFoo(42u); + (void)x; + (void)y; + }; +} + +// PR 12325 - this was a false uninitialized value warning due to +// a broken CFG. +int pr12325(int params) { + int x = ({ + while (false) + ; + int _v = params; + if (false) + ; + _v; // no-warning + }); + return x; +} + +// Test lambda expressions with -Wuninitialized +int test_lambda() { + auto f1 = [] (int x, int y) { int z; return x + y + z; }; // expected-warning {{C++11 requires lambda with omitted result type to consist of a single return statement}} expected-warning{{variable 'z' is uninitialized when used here}} expected-note {{initialize the variable 'z' to silence this warning}} + return f1(1, 2); +} diff --git a/test/SemaCXX/unknown-anytype-blocks.cpp b/test/SemaCXX/unknown-anytype-blocks.cpp new file mode 100644 index 0000000..86ce7e1 --- /dev/null +++ b/test/SemaCXX/unknown-anytype-blocks.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -funknown-anytype -fblocks -fsyntax-only -verify -std=c++11 %s + +namespace test1 { + __unknown_anytype (^foo)(); + __unknown_anytype (^bar)(); + int test() { + auto ret1 = (int)foo(); + auto ret2 = bar(); // expected-error {{'bar' has unknown return type; cast the call to its declared return type}} + return ret1; + } +} diff --git a/test/SemaCXX/unknown-anytype.cpp b/test/SemaCXX/unknown-anytype.cpp index ba52122..a07ec83 100644 --- a/test/SemaCXX/unknown-anytype.cpp +++ b/test/SemaCXX/unknown-anytype.cpp @@ -14,9 +14,9 @@ namespace test1 { // making sure that these locations check for placeholder types // properly. - int x = foo; // expected-error {{cannot initialize}} + int x = foo; // expected-error {{'foo' has unknown type}} int y = 0 + foo; // expected-error {{'foo' has unknown type}} - return foo; // expected-error {{cannot initialize}} + return foo; // expected-error {{'foo' has unknown type}} } } diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp index 19be03a..4e3acbb 100644 --- a/test/SemaCXX/value-initialization.cpp +++ b/test/SemaCXX/value-initialization.cpp @@ -1,11 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -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}} +struct A { // expected-warning {{does not declare any constructor to initialize}} + const int i; // expected-note{{const member 'i' will never be initialized}} expected-note {{implicitly deleted}} virtual void f() { } }; int main () { - (void)A(); // expected-error {{call to deleted constructor}} + (void)A(); // expected-error {{call to implicitly-deleted default constructor}} } diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index 42c27fb..86b560e 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wnon-pod-varargs +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs extern char version[]; @@ -118,3 +118,8 @@ void t8(int n, ...) { (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}} __builtin_va_end(list); } + +int t9(int n) { + // Make sure the error works in potentially-evaluated sizeof + return (int)sizeof(*(Helper(Foo()), (int (*)[n])0)); // expected-warning{{cannot pass object of non-POD type}} +} diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 4d3d939..82245ac 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -218,3 +218,52 @@ void test(fltx2 fltx2_val, fltx4 fltx4_val, dblx2 dblx2_val, dblx4 dblx4_val) { // Scalar-to-vector conversions. accept_fltx2(1.0); // expected-error{{no matching function for call to 'accept_fltx2'}} } + +typedef int intx4 __attribute__((__vector_size__(16))); +typedef int inte4 __attribute__((__ext_vector_type__(4))); +typedef int flte4 __attribute__((__ext_vector_type__(4))); + +void test_mixed_vector_types(fltx4 f, intx4 n, flte4 g, flte4 m) { + (void)(f == g); + (void)(g != f); + (void)(f <= g); + (void)(g >= f); + (void)(f < g); + (void)(g > f); + + (void)(+g); + (void)(-g); + + (void)(f + g); + (void)(f - g); + (void)(f * g); + (void)(f / g); + (void)(f = g); + (void)(f += g); + (void)(f -= g); + (void)(f *= g); + (void)(f /= g); + + + (void)(n == m); + (void)(m != n); + (void)(n <= m); + (void)(m >= n); + (void)(n < m); + (void)(m > n); + + (void)(+m); + (void)(-m); + (void)(~m); + + (void)(n + m); + (void)(n - m); + (void)(n * m); + (void)(n / m); + (void)(n % m); + (void)(n = m); + (void)(n += m); + (void)(n -= m); + (void)(n *= m); + (void)(n /= m); +} diff --git a/test/SemaCXX/vla.cpp b/test/SemaCXX/vla.cpp new file mode 100644 index 0000000..d63b633 --- /dev/null +++ b/test/SemaCXX/vla.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -verify %s + +// PR11925 +int n; +int (&f())[n]; // expected-error {{function declaration cannot have variably modified type}} diff --git a/test/SemaCXX/warn-bool-conversion.cpp b/test/SemaCXX/warn-bool-conversion.cpp index 595c749..b3d136e 100644 --- a/test/SemaCXX/warn-bool-conversion.cpp +++ b/test/SemaCXX/warn-bool-conversion.cpp @@ -1,18 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int* j = false; // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} +int* j = false; // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} -void foo(int* i, int *j=(false)) // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} +void foo(int* i, int *j=(false)) // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} { - foo(false); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} + foo(false); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} foo((int*)false); // no-warning: explicit cast foo(0); // no-warning: not a bool, even though its convertible to bool - foo(false == true); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} - foo((42 + 24) < 32); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} + foo(false == true); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} + foo((42 + 24) < 32); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} const bool kFlag = false; - foo(kFlag); // expected-warning{{ initialization of pointer of type 'int *' to null from a constant boolean expression}} + foo(kFlag); // expected-warning{{initialization of pointer of type 'int *' to null from a constant boolean expression}} } char f(struct Undefined*); diff --git a/test/SemaCXX/warn-empty-body.cpp b/test/SemaCXX/warn-empty-body.cpp new file mode 100644 index 0000000..d643ced --- /dev/null +++ b/test/SemaCXX/warn-empty-body.cpp @@ -0,0 +1,271 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void a(int i); +int b(); +int c(); + +void test1(int x, int y) { + while(true) { + if (x); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + + int i; + // PR11329 + for (i = 0; i < x; i++); { // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + b(); + } + + for (i = 0; i < x; i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + { + a(i); + } + + for (i = 0; + i < x; + i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + { + a(i); + } + + int arr[3] = { 1, 2, 3 }; + for (int j : arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + for (int j : + arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + while (b() == 0); { // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + } + + while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + { + a(i); + } + + while (b() == 0 || + c() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + { + a(i); + } + + do; // expected-note{{to match this 'do'}} + b(); // expected-error{{expected 'while' in do/while loop}} + while (b()); // no-warning + c(); + + do; // expected-note{{to match this 'do'}} + b(); // expected-error{{expected 'while' in do/while loop}} + while (b()); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + c(); + + switch(x) // no-warning + { + switch(y); // expected-warning{{switch statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + { + case 0: + a(10); + break; + default: + a(20); + break; + } + } + } +} + +/// There should be no warning when null statement is placed on its own line. +void test2(int x, int y) { + if (x) // no-warning + ; // no-warning + + int i; + for (i = 0; i < x; i++) // no-warning + ; // no-warning + + for (i = 0; + i < x; + i++) // no-warning + ; // no-warning + + int arr[3] = { 1, 2, 3 }; + for (int j : arr) // no-warning + ; // no-warning + + while (b() == 0) // no-warning + ; // no-warning + + while (b() == 0 || + c() == 0) // no-warning + ; // no-warning + + switch(x) + { + switch(y) // no-warning + ; // no-warning + } + + // Last `for' or `while' statement in compound statement shouldn't warn. + while(b() == 0); // no-warning +} + +/// There should be no warning for a null statement resulting from an empty macro. +#define EMPTY(a) +void test3(int x, int y) { + if (x) EMPTY(x); // no-warning + + int i; + for (i = 0; i < x; i++) EMPTY(i); // no-warning + + for (i = 0; + i < x; + i++) EMPTY(i); // no-warning + + int arr[3] = { 1, 2, 3 }; + for (int j : arr) EMPTY(j); // no-warning + + for (int j : + arr) EMPTY(j); // no-warning + + while (b() == 0) EMPTY(i); // no-warning + + while (b() == 0 || + c() == 0) EMPTY(i); // no-warning + + switch (x) { + switch (y) + EMPTY(i); // no-warning + } +} + +void test4(int x) +{ + // Idiom used in some metaprogramming constructs. + switch (x) default:; // no-warning + + // Frequent idiom used in macros. + do {} while (false); // no-warning +} + +/// There should be no warning for a common for/while idiom when it is obvious +/// from indentation that next statement wasn't meant to be a body. +void test5(int x, int y) { + int i; + for (i = 0; i < x; i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + for (i = 0; i < x; i++); // no-warning + a(i); + + for (i = 0; + i < x; + i++); // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + for (i = 0; + i < x; + i++); // no-warning + a(i); + + while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + while (b() == 0); // no-warning + a(i); + + while (b() == 0 || + c() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(i); + + while (b() == 0 || + c() == 0); // no-warning + a(i); +} + +/// There should be no warning for a statement with a non-null body. +void test6(int x, int y) { + if (x) {} // no-warning + + if (x) + a(x); // no-warning + + int i; + for (i = 0; i < x; i++) // no-warning + a(i); // no-warning + + for (i = 0; i < x; i++) { // no-warning + a(i); // no-warning + } + + for (i = 0; + i < x; + i++) // no-warning + a(i); // no-warning + + int arr[3] = { 1, 2, 3 }; + for (int j : arr) // no-warning + a(j); + + for (int j : arr) {} // no-warning + + while (b() == 0) // no-warning + a(i); // no-warning + + while (b() == 0) {} // no-warning + + switch(x) // no-warning + { + switch(y) // no-warning + { + case 0: + a(10); + break; + default: + a(20); + break; + } + } +} + +void test_errors(int x) { + if (1) + aa; // expected-error{{use of undeclared identifier}} + // no empty body warning. + + int i; + for (i = 0; i < x; i++) + bb; // expected-error{{use of undeclared identifier}} + + int arr[3] = { 1, 2, 3 }; + for (int j : arr) + cc; // expected-error{{use of undeclared identifier}} + + while (b() == 0) + dd; // expected-error{{use of undeclared identifier}} +} + +// Warnings for statements in templates shouldn't be duplicated for all +// instantiations. +template <typename T> +void test_template(int x) { + if (x); // expected-warning{{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + + if (x) + EMPTY(x); // no-warning + + int arr[3] = { 1, 2, 3 }; + for (int j : arr); // expected-warning{{range-based for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + + while (b() == 0); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}} + a(x); +} + +void test_template_inst(int x) { + test_template<int>(x); + test_template<double>(x); +} + diff --git a/test/SemaCXX/warn-everthing.cpp b/test/SemaCXX/warn-everthing.cpp new file mode 100644 index 0000000..144a8f9 --- /dev/null +++ b/test/SemaCXX/warn-everthing.cpp @@ -0,0 +1,13 @@ +// RUN: %clang -Weverything -fsyntax-only %s -verify + +// This previously crashed due to a bug in the CFG. Exercising all +// warnings helps check CFG construction. +class PR12271 { +public: + PR12271(); + ~PR12271(); +}; + +void testPR12271() { + PR12271 a[1][1]; +}
\ No newline at end of file diff --git a/test/SemaCXX/warn-func-as-bool.cpp b/test/SemaCXX/warn-func-as-bool.cpp new file mode 100644 index 0000000..b5df744 --- /dev/null +++ b/test/SemaCXX/warn-func-as-bool.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -x c++ -verify -fsyntax-only %s + +void f1(); + +struct S { + static void f2(); +}; + +extern void f3() __attribute__((weak_import)); + +struct S2 { + static void f4() __attribute__((weak_import)); +}; + +bool f5(); +bool f6(int); + +void bar() { + bool b; + + b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} \ + expected-note {{suffix with parentheses to turn this into a function call}} + b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + + // implicit casts of weakly imported symbols are ok: + b = f3; + if (f3) {} + b = S2::f4; + if (S2::f4) {} +} diff --git a/test/SemaCXX/warn-large-by-value-copy.cpp b/test/SemaCXX/warn-large-by-value-copy.cpp index 39dbd76..3e419ec 100644 --- a/test/SemaCXX/warn-large-by-value-copy.cpp +++ b/test/SemaCXX/warn-large-by-value-copy.cpp @@ -40,3 +40,8 @@ void g() { } } + +template<typename T> class DependentPOD { + enum b { x }; + b foo() { return x; } +}; diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp index a018223..e0d28da 100644 --- a/test/SemaCXX/warn-memset-bad-sizeof.cpp +++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -104,6 +104,14 @@ void f(Mat m, const Foo& const_foo, char *buffer) { // Copy to raw buffer shouldn't warn either memcpy(&foo, &arr, sizeof(Foo)); memcpy(&arr, &foo, sizeof(Foo)); + + // Shouldn't warn, and shouldn't crash either. + memset(({ + if (0) {} + while (0) {} + for (;;) {} + &s; + }), 0, sizeof(s)); } namespace ns { @@ -132,8 +140,6 @@ void strcpy_and_friends() { strncpy(buff, BAR, sizeof(BAR)); // \ // expected-warning {{argument to 'sizeof' in 'strncpy' call is the same expression as the source}} - strncat(buff, BAR, sizeof(BAR)); // \ - // expected-warning {{argument to 'sizeof' in 'strncat' call is the same expression as the source}} strndup(FOO, sizeof(FOO)); // \ // expected-warning {{argument to 'sizeof' in 'strndup' call is the same expression as the source}} } diff --git a/test/SemaCXX/warn-new-overaligned-2.cpp b/test/SemaCXX/warn-new-overaligned-2.cpp new file mode 100644 index 0000000..5505009 --- /dev/null +++ b/test/SemaCXX/warn-new-overaligned-2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned -verify %s + +// This test verifies that we don't warn when the global operator new is +// overridden. That's why we can't merge this with the other test file. + +void* operator new(unsigned long); +void* operator new[](unsigned long); + +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; + new Test[10]; +} diff --git a/test/SemaCXX/warn-new-overaligned-3.cpp b/test/SemaCXX/warn-new-overaligned-3.cpp new file mode 100644 index 0000000..c9a57fb --- /dev/null +++ b/test/SemaCXX/warn-new-overaligned-3.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned %s -isystem %S/Inputs -verify + +// This test ensures that we still get the warning even if we #include <new> +// where the header here simulates <new>. +#include <warn-new-overaligned-3.h> + +namespace test1 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test2 { +struct helper { int i __attribute__((aligned(256))); }; + +struct Placement { + Placement() { + new (d) helper(); + } + helper *d; +}; +} diff --git a/test/SemaCXX/warn-new-overaligned.cpp b/test/SemaCXX/warn-new-overaligned.cpp new file mode 100644 index 0000000..42a4e35 --- /dev/null +++ b/test/SemaCXX/warn-new-overaligned.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wover-aligned -verify %s + +namespace test1 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test2 { +class Test { + typedef int __attribute__((aligned(256))) aligned_int; + aligned_int high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test3 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + void* operator new(unsigned long) { + return 0; + } + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; + new Test[10]; // expected-warning {{type 'test3::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test4 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + void* operator new[](unsigned long) { + return 0; + } + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test4::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; +} +} diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 90a8933..566e5c1 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -36,6 +36,18 @@ class __attribute__((lockable)) Mutex { void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); }; +class __attribute__((scoped_lockable)) MutexLock { + public: + MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); + ~MutexLock() __attribute__((unlock_function)); +}; + +class __attribute__((scoped_lockable)) ReaderMutexLock { + public: + ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu))); + ~ReaderMutexLock() __attribute__((unlock_function)); +}; + Mutex sls_mu; @@ -160,30 +172,29 @@ void sls_fun_bad_2() { } void sls_fun_bad_3() { - sls_mu.Lock(); // \ - // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_3'}} -} + sls_mu.Lock(); // expected-note {{mutex acquired here}} +} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} void sls_fun_bad_4() { if (getBool()) sls_mu.Lock(); // \ - // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \ + expected-note{{mutex acquired here}} + else sls_mu2.Lock(); // \ - // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}} -} + expected-note{{mutex acquired here}} +} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} void sls_fun_bad_5() { - sls_mu.Lock(); // \ - // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + sls_mu.Lock(); // expected-note {{mutex acquired here}} if (getBool()) sls_mu.Unlock(); -} +} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} void sls_fun_bad_6() { if (getBool()) { - sls_mu.Lock(); // \ - // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + sls_mu.Lock(); // expected-note {{mutex acquired here}} } else { if (getBool()) { getBool(); // EMPTY @@ -192,29 +203,30 @@ void sls_fun_bad_6() { } } sls_mu.Unlock(); // \ - // expected-warning{{unlocking 'sls_mu' that was not locked}} + expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\ + expected-warning{{unlocking 'sls_mu' that was not locked}} } void sls_fun_bad_7() { - sls_mu.Lock(); // \ - // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + sls_mu.Lock(); while (getBool()) { sls_mu.Unlock(); if (getBool()) { if (getBool()) { - continue; + continue; // \ + expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} } } - sls_mu.Lock(); // \ - // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}} + sls_mu.Lock(); // expected-note {{mutex acquired here}} } sls_mu.Unlock(); } void sls_fun_bad_8() { - sls_mu.Lock(); // \ - // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} - do { + sls_mu.Lock(); // expected-note{{mutex acquired here}} + + // FIXME: TERRIBLE SOURCE LOCATION! + do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} sls_mu.Unlock(); } while (getBool()); } @@ -222,29 +234,42 @@ void sls_fun_bad_8() { void sls_fun_bad_9() { do { sls_mu.Lock(); // \ - // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \ + // expected-note{{mutex acquired here}} } while (getBool()); sls_mu.Unlock(); } void sls_fun_bad_10() { - sls_mu.Lock(); // \ - // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_10'}} \ - // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + sls_mu.Lock(); // expected-note 2{{mutex acquired here}} while(getBool()) { - sls_mu.Unlock(); + sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} } -} +} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} void sls_fun_bad_11() { - while (getBool()) { - sls_mu.Lock(); // \ - // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + while (getBool()) { // \ + expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} + sls_mu.Lock(); // expected-note {{mutex acquired here}} } sls_mu.Unlock(); // \ // expected-warning{{unlocking 'sls_mu' that was not locked}} } +void sls_fun_bad_12() { + sls_mu.Lock(); // expected-note {{mutex acquired here}} + while (getBool()) { + sls_mu.Unlock(); + if (getBool()) { + if (getBool()) { + break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} + } + } + sls_mu.Lock(); + } + sls_mu.Unlock(); +} + //-----------------------------------------// // Handling lock expressions in attribute args // -------------------------------------------// @@ -277,9 +302,8 @@ void aa_fun_bad_2() { } void aa_fun_bad_3() { - glock.globalLock(); // \ - // expected-warning{{mutex 'aa_mu' is still locked at the end of function 'aa_fun_bad_3'}} -} + glock.globalLock(); // expected-note{{mutex acquired here}} +} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}} //--------------------------------------------------// // Regression tests for unusual method names @@ -289,23 +313,20 @@ Mutex wmu; // Test diagnostics for other method names. class WeirdMethods { + // FIXME: can't currently check inside constructors and destructors. WeirdMethods() { - wmu.Lock(); // \ - // expected-warning {{mutex 'wmu' is still locked at the end of function 'WeirdMethods'}} - } + wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}} + } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}} ~WeirdMethods() { - wmu.Lock(); // \ - // expected-warning {{mutex 'wmu' is still locked at the end of function '~WeirdMethods'}} - } + wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}} + } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}} void operator++() { - wmu.Lock(); // \ - // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator++'}} - } + wmu.Lock(); // expected-note {{mutex acquired here}} + } // expected-warning {{mutex 'wmu' is still locked at the end of function}} operator int*() { - wmu.Lock(); // \ - // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator int *'}} + wmu.Lock(); // expected-note {{mutex acquired here}} return 0; - } + } // expected-warning {{mutex 'wmu' is still locked at the end of function}} }; //-----------------------------------------------// @@ -740,32 +761,12 @@ void es_bad_7() { sls_mu.Unlock(); } + //-----------------------------------------------// // Unparseable lock expressions // ----------------------------------------------// -Mutex UPmu; -// FIXME: add support for lock expressions involving arrays. -Mutex mua[5]; - -int x __attribute__((guarded_by(UPmu = sls_mu))); // \ - // expected-warning{{cannot resolve lock expression to a specific lockable object}} -int y __attribute__((guarded_by(mua[0]))); // \ - // expected-warning{{cannot resolve lock expression to a specific lockable object}} - - -void testUnparse() { - // no errors, since the lock expressions are not resolved - x = 5; - y = 5; -} - -void testUnparse2() { - mua[0].Lock(); // \ - // expected-warning{{cannot resolve lock expression to a specific lockable object}} - (&(mua[0]) + 4)->Lock(); // \ - // expected-warning{{cannot resolve lock expression to a specific lockable object}} -} +// FIXME -- derive new tests for unhandled expressions //----------------------------------------------------------------------------// @@ -1152,7 +1153,7 @@ class Foo { int Foo::foo() { int res; - w = 5.2; + w = 5; res = a_ + 5; return res; } @@ -1166,7 +1167,7 @@ void Foo::bar() mu_.Unlock(); if (x > 5) { mu1.Lock(); - g = 2.3; + g = 2; mu1.Unlock(); } } @@ -1184,7 +1185,7 @@ void main() f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}} f2->mu_.Unlock(); mu2.Lock(); - w = 2.5; + w = 2; mu2.Unlock(); } } // end namespace thread_annot_lock_13 @@ -1420,3 +1421,823 @@ void main() } // end namespace thread_annot_lock_67_modified +namespace substitution_test { + class MyData { + public: + Mutex mu; + + void lockData() __attribute__((exclusive_lock_function(mu))) { } + void unlockData() __attribute__((unlock_function(mu))) { } + + void doSomething() __attribute__((exclusive_locks_required(mu))) { } + }; + + + class DataLocker { + public: + void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { } + void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { } + }; + + + class Foo { + public: + void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { } + + void bar1(MyData* d) { + d->lockData(); + foo(d); + d->unlockData(); + } + + void bar2(MyData* d) { + DataLocker dlr; + dlr.lockData(d); + foo(d); + dlr.unlockData(d); + } + + void bar3(MyData* d1, MyData* d2) { + DataLocker dlr; + dlr.lockData(d1); // expected-note {{mutex acquired here}} + dlr.unlockData(d2); // \ + // expected-warning {{unlocking 'mu' that was not locked}} + } // expected-warning {{mutex 'mu' is still locked at the end of function}} + + void bar4(MyData* d1, MyData* d2) { + DataLocker dlr; + dlr.lockData(d1); + foo(d2); // \ + // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}} + dlr.unlockData(d1); + } + }; +} // end namespace substituation_test + + + +namespace constructor_destructor_tests { + Mutex fooMu; + int myVar GUARDED_BY(fooMu); + + class Foo { + public: + Foo() __attribute__((exclusive_lock_function(fooMu))) { } + ~Foo() __attribute__((unlock_function(fooMu))) { } + }; + + void fooTest() { + Foo foo; + myVar = 0; + } +} + + +namespace invalid_lock_expression_test { + +class LOCKABLE MyLockable { +public: + MyLockable() __attribute__((exclusive_lock_function)) { } + ~MyLockable() { } +}; + +// create an empty lock expression +void foo() { + MyLockable lock; // \ + // expected-warning {{cannot resolve lock expression}} +} + +} // end namespace invalid_lock_expression_test + +namespace template_member_test { + + struct S { int n; }; + struct T { + Mutex m; + S *s GUARDED_BY(this->m); + }; + Mutex m; + struct U { + union { + int n; + }; + } *u GUARDED_BY(m); + + template<typename U> + struct IndirectLock { + int DoNaughtyThings(T *t) { + u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}} + return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}} + } + }; + + template struct IndirectLock<int>; // expected-note {{here}} + + struct V { + void f(int); + void f(double); + + Mutex m; + V *p GUARDED_BY(this->m); + }; + template<typename U> struct W { + V v; + void f(U u) { + v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}} + } + }; + template struct W<int>; // expected-note {{here}} + +} + +namespace test_scoped_lockable { + +struct TestScopedLockable { + Mutex mu1; + Mutex mu2; + int a __attribute__((guarded_by(mu1))); + int b __attribute__((guarded_by(mu2))); + + bool getBool(); + + void foo1() { + MutexLock mulock(&mu1); + a = 5; + } + + void foo2() { + ReaderMutexLock mulock1(&mu1); + if (getBool()) { + MutexLock mulock2a(&mu2); + b = a + 1; + } + else { + MutexLock mulock2b(&mu2); + b = a + 2; + } + } + + void foo3() { + MutexLock mulock_a(&mu1); + MutexLock mulock_b(&mu1); // \ + // expected-warning {{locking 'mu1' that is already locked}} + } // expected-warning {{unlocking 'mu1' that was not locked}} + + void foo4() { + MutexLock mulock1(&mu1), mulock2(&mu2); + a = b+1; + b = a+1; + } +}; + +} // end namespace test_scoped_lockable + + +namespace FunctionAttrTest { + +class Foo { +public: + Mutex mu_; + int a GUARDED_BY(mu_); +}; + +Foo fooObj; + +void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_); + +void bar() { + foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} + fooObj.mu_.Lock(); + foo(); + fooObj.mu_.Unlock(); +} + +}; // end namespace FunctionAttrTest + + +struct TestTryLock { + Mutex mu; + int a GUARDED_BY(mu); + bool cond; + + void foo1() { + if (mu.TryLock()) { + a = 1; + mu.Unlock(); + } + } + + void foo2() { + if (!mu.TryLock()) return; + a = 2; + mu.Unlock(); + } + + void foo3() { + bool b = mu.TryLock(); + if (b) { + a = 3; + mu.Unlock(); + } + } + + void foo4() { + bool b = mu.TryLock(); + if (!b) return; + a = 4; + mu.Unlock(); + } + + void foo5() { + while (mu.TryLock()) { + a = a + 1; + mu.Unlock(); + } + } + + void foo6() { + bool b = mu.TryLock(); + b = !b; + if (b) return; + a = 6; + mu.Unlock(); + } + + void foo7() { + bool b1 = mu.TryLock(); + bool b2 = !b1; + bool b3 = !b2; + if (b3) { + a = 7; + mu.Unlock(); + } + } + + // Test use-def chains: join points + void foo8() { + bool b = mu.TryLock(); + bool b2 = b; + if (cond) + b = true; + if (b) { // b should be unknown at this point, becuase of the join point + a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}} + } + if (b2) { // b2 should be known at this point. + a = 8; + mu.Unlock(); + } + } + + // Test use-def-chains: back edges + void foo9() { + bool b = mu.TryLock(); + + for (int i = 0; i < 10; ++i); + + if (b) { // b is still known, because the loop doesn't alter it + a = 9; + mu.Unlock(); + } + } + + // Test use-def chains: back edges + void foo10() { + bool b = mu.TryLock(); + + while (cond) { + if (b) { // b should be uknown at this point b/c of the loop + a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}} + } + b = !b; + } + } +}; // end TestTrylock + + +namespace TestTemplateAttributeInstantiation { + +class Foo1 { +public: + Mutex mu_; + int a GUARDED_BY(mu_); +}; + +class Foo2 { +public: + int a GUARDED_BY(mu_); + Mutex mu_; +}; + + +class Bar { +public: + // Test non-dependent expressions in attributes on template functions + template <class T> + void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) { + foo->a = 0; + } + + // Test dependent expressions in attributes on template functions + template <class T> + void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) { + fooT->a = 0; + } +}; + + +template <class T> +class BarT { +public: + Foo1 fooBase; + T fooBaseT; + + // Test non-dependent expression in ordinary method on template class + void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) { + fooBase.a = 0; + } + + // Test dependent expressions in ordinary methods on template class + void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) { + fooBaseT.a = 0; + } + + // Test dependent expressions in template method in template class + template <class T2> + void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) { + fooBaseT.a = 0; + fooT->a = 0; + } +}; + +template <class T> +class Cell { +public: + Mutex mu_; + // Test dependent guarded_by + T data GUARDED_BY(mu_); + + void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) { + data = 0; + } + + void foo() { + mu_.Lock(); + data = 0; + mu_.Unlock(); + } +}; + +void test() { + Bar b; + BarT<Foo2> bt; + Foo1 f1; + Foo2 f2; + + f1.mu_.Lock(); + f2.mu_.Lock(); + bt.fooBase.mu_.Lock(); + bt.fooBaseT.mu_.Lock(); + + b.barND(&f1, &f2); + b.barD(&f1, &f2); + bt.barND(); + bt.barD(); + bt.barTD(&f2); + + f1.mu_.Unlock(); + bt.barTD(&f1); // \ + // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}} + + bt.fooBase.mu_.Unlock(); + bt.fooBaseT.mu_.Unlock(); + f2.mu_.Unlock(); + + Cell<int> cell; + cell.data = 0; // \ + // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}} + cell.foo(); + cell.mu_.Lock(); + cell.fooEx(); + cell.mu_.Unlock(); +} + + +template <class T> +class CellDelayed { +public: + // Test dependent guarded_by + T data GUARDED_BY(mu_); + static T static_data GUARDED_BY(static_mu_); + + void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) { + this->data = other->data; + } + + template <class T2> + void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) { + this->data = otherT->data; + } + + void foo() { + mu_.Lock(); + data = 0; + mu_.Unlock(); + } + + Mutex mu_; + static Mutex static_mu_; +}; + +void testDelayed() { + CellDelayed<int> celld; + CellDelayed<int> celld2; + celld.foo(); + celld.mu_.Lock(); + celld2.mu_.Lock(); + + celld.fooEx(&celld2); + celld.fooExT(&celld2); + + celld2.mu_.Unlock(); + celld.mu_.Unlock(); +} + +}; // end namespace TestTemplateAttributeInstantiation + + +namespace FunctionDeclDefTest { + +class Foo { +public: + Mutex mu_; + int a GUARDED_BY(mu_); + + virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_); +}; + +// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_ +void Foo::foo1(Foo *f_defined) { + f_defined->a = 0; +}; + +void test() { + Foo myfoo; + myfoo.foo1(&myfoo); // \ + // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}} + myfoo.mu_.Lock(); + myfoo.foo1(&myfoo); + myfoo.mu_.Unlock(); +} + +}; + +namespace GoingNative { + + struct __attribute__((lockable)) mutex { + void lock() __attribute__((exclusive_lock_function)); + void unlock() __attribute__((unlock_function)); + // ... + }; + bool foo(); + bool bar(); + mutex m; + void test() { + m.lock(); + while (foo()) { + m.unlock(); + // ... + if (bar()) { + // ... + if (foo()) + continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}} + //... + } + // ... + m.lock(); // expected-note {{mutex acquired here}} + } + m.unlock(); + } + +} + + + +namespace FunctionDefinitionTest { + +class Foo { +public: + void foo1(); + void foo2(); + void foo3(Foo *other); + + template<class T> + void fooT1(const T& dummy1); + + template<class T> + void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_); + + Mutex mu_; + int a GUARDED_BY(mu_); +}; + +template<class T> +class FooT { +public: + void foo(); + + Mutex mu_; + T a GUARDED_BY(mu_); +}; + + +void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS { + a = 1; +} + +void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) { + a = 2; +} + +void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) { + other->a = 3; +} + +template<class T> +void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) { + a = dummy1; +} + +/* TODO -- uncomment with template instantiation of attributes. +template<class T> +void Foo::fooT2(const T& dummy2) { + a = dummy2; +} +*/ + +void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { + f->a = 1; +} + +void fooF2(Foo *f); +void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { + f->a = 2; +} + +void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_); +void fooF3(Foo *f) { + f->a = 3; +} + +template<class T> +void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { + a = 0; +} + +void test() { + int dummy = 0; + Foo myFoo; + + myFoo.foo2(); // \ + // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}} + myFoo.foo3(&myFoo); // \ + // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}} + myFoo.fooT1(dummy); // \ + // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}} + + // FIXME: uncomment with template instantiation of attributes patch + // myFoo.fooT2(dummy); // expected warning + + fooF1(&myFoo); // \ + // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}} + fooF2(&myFoo); // \ + // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}} + fooF3(&myFoo); // \ + // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}} + + myFoo.mu_.Lock(); + myFoo.foo2(); + myFoo.foo3(&myFoo); + myFoo.fooT1(dummy); + + // FIXME: uncomment with template instantiation of attributes patch + // myFoo.fooT2(dummy); + + fooF1(&myFoo); + fooF2(&myFoo); + fooF3(&myFoo); + myFoo.mu_.Unlock(); + + FooT<int> myFooT; + myFooT.foo(); // \ + // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}} +} + +} // end namespace FunctionDefinitionTest + + +namespace SelfLockingTest { + +class LOCKABLE MyLock { +public: + int foo GUARDED_BY(this); + + void lock() EXCLUSIVE_LOCK_FUNCTION(); + void unlock() UNLOCK_FUNCTION(); + + void doSomething() { + this->lock(); // allow 'this' as a lock expression + foo = 0; + doSomethingElse(); + this->unlock(); + } + + void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) { + foo = 1; + }; + + void test() { + foo = 2; // \ + // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}} + } +}; + + +class LOCKABLE MyLock2 { +public: + Mutex mu_; + int foo GUARDED_BY(this); + + // don't check inside lock and unlock functions + void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); } + void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); } + + // don't check inside constructors and destructors + MyLock2() { foo = 1; } + ~MyLock2() { foo = 0; } +}; + + +} // end namespace SelfLockingTest + + +namespace InvalidNonstatic { + +// Forward decl here causes bogus "invalid use of non-static data member" +// on reference to mutex_ in guarded_by attribute. +class Foo; + +class Foo { + Mutex* mutex_; + + int foo __attribute__((guarded_by(mutex_))); +}; + +} // end namespace InvalidNonStatic + + +namespace NoReturnTest { + +bool condition(); +void fatal() __attribute__((noreturn)); + +Mutex mu_; + +void test1() { + MutexLock lock(&mu_); + if (condition()) { + fatal(); + return; + } +} + +} // end namespace NoReturnTest + + +namespace TestMultiDecl { + +class Foo { +public: + int GUARDED_BY(mu_) a; + int GUARDED_BY(mu_) b, c; + + void foo() { + a = 0; // \ + // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + b = 0; // \ + // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}} + c = 0; // \ + // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}} + } + +private: + Mutex mu_; +}; + +} // end namespace TestMultiDecl + + +namespace WarnNoDecl { + +class Foo { + void foo(int a); __attribute__(( // \ + // expected-warning {{declaration does not declare anything}} + exclusive_locks_required(a))); // \ + // expected-warning {{attribute exclusive_locks_required ignored}} +}; + +} // end namespace WarnNoDecl + + + +namespace MoreLockExpressions { + +class Foo { +public: + Mutex mu_; + int a GUARDED_BY(mu_); +}; + +class Bar { +public: + int b; + Foo* f; + + Foo& getFoo() { return *f; } + Foo& getFoo2(int c) { return *f; } + Foo& getFoo3(int c, int d) { return *f; } + + Foo& getFooey() { return *f; } +}; + +Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); } + +void test() { + Foo foo; + Foo *fooArray; + Bar bar; + int a; + int b; + int c; + + bar.getFoo().mu_.Lock(); + bar.getFoo().a = 0; + bar.getFoo().mu_.Unlock(); + + (bar.getFoo().mu_).Lock(); // test parenthesis + bar.getFoo().a = 0; + (bar.getFoo().mu_).Unlock(); + + bar.getFoo2(a).mu_.Lock(); + bar.getFoo2(a).a = 0; + bar.getFoo2(a).mu_.Unlock(); + + bar.getFoo3(a, b).mu_.Lock(); + bar.getFoo3(a, b).a = 0; + bar.getFoo3(a, b).mu_.Unlock(); + + getBarFoo(bar, a).mu_.Lock(); + getBarFoo(bar, a).a = 0; + getBarFoo(bar, a).mu_.Unlock(); + + bar.getFoo2(10).mu_.Lock(); + bar.getFoo2(10).a = 0; + bar.getFoo2(10).mu_.Unlock(); + + bar.getFoo2(a + 1).mu_.Lock(); + bar.getFoo2(a + 1).a = 0; + bar.getFoo2(a + 1).mu_.Unlock(); + + (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); + (a > 0 ? fooArray[1] : fooArray[b]).a = 0; + (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); + + bar.getFoo().mu_.Lock(); + bar.getFooey().a = 0; // \ + // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + bar.getFoo().mu_.Unlock(); + + bar.getFoo2(a).mu_.Lock(); + bar.getFoo2(b).a = 0; // \ + // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + bar.getFoo2(a).mu_.Unlock(); + + bar.getFoo3(a, b).mu_.Lock(); + bar.getFoo3(a, c).a = 0; // \ + // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + bar.getFoo3(a, b).mu_.Unlock(); + + getBarFoo(bar, a).mu_.Lock(); + getBarFoo(bar, b).a = 0; // \ + // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + getBarFoo(bar, a).mu_.Unlock(); + + (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock(); + (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \ + // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock(); +} + + +} // end namespace + + diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index 67882d0..587cb8a 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -1,9 +1,26 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s +#define LOCKABLE __attribute__ ((lockable)) +#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) +#define GUARDED_BY(x) __attribute__ ((guarded_by(x))) +#define GUARDED_VAR __attribute__ ((guarded_var)) +#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) +#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) +#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) +#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) +#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) +#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) +#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) +#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) \ + __attribute__ ((exclusive_locks_required(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) \ + __attribute__ ((shared_locks_required(__VA_ARGS__))) +#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) -//-----------------------------------------// -// Helper fields -//-----------------------------------------// class __attribute__((lockable)) Mu { public: @@ -324,13 +341,13 @@ int gb_var_arg_8 __attribute__((guarded_by(muPointer))); // illegal attribute arguments int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \ - // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'int'}} int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \ - // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'const char [3]'}} int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \ - // expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'guarded_by' attribute requires arguments that are class type or point to class type; type here is 'class Mu **'}} int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \ - // expected-error {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute; type here is 'class UnlockableMu'}} //3. // Thread Safety analysis tests @@ -395,13 +412,13 @@ int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer))); // illegal attribute arguments int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \ - // expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \ - // expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \ - // expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}} int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \ - // expected-error {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}} //-----------------------------------------// @@ -456,15 +473,15 @@ Mu aa_var_arg_8 __attribute__((acquired_after(muPointer))); // illegal attribute arguments Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \ - // expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \ - // expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \ - // expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_after' attribute requires arguments that are class type or point to class type}} Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \ - // expected-error {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}} UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \ - // expected-error {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}} + // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}} //-----------------------------------------// // Acquired Before (ab) @@ -519,15 +536,15 @@ Mu ab_var_arg_8 __attribute__((acquired_before(muPointer))); // illegal attribute arguments Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \ - // expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \ - // expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \ - // expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'acquired_before' attribute requires arguments that are class type or point to class type}} Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \ - // expected-error {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}} UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \ - // expected-error {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}} + // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}} //-----------------------------------------// @@ -586,11 +603,11 @@ int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2))); // illegal attribute arguments int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \ - // expected-error {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \ - // expected-error {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}} int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \ - // expected-error {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \ // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -658,11 +675,11 @@ int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2))); // illegal attribute arguments int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \ - // expected-error {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \ - // expected-error {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_lock_function' attribute requires arguments that are class type or point to class type}} int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \ - // expected-error {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \ // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -686,7 +703,7 @@ int slf_function_bad_7() __attribute__((shared_lock_function(0))); // \ // plus an optional list of locks (vars/fields) void etf_function() __attribute__((exclusive_trylock_function)); // \ - // expected-error {{attribute takes attribute takes at least 1 argument arguments}} + // expected-error {{attribute takes at least 1 argument}} void etf_function_args() __attribute__((exclusive_trylock_function(1, mu2))); @@ -740,11 +757,11 @@ int etf_function_bad_3() __attribute__((exclusive_trylock_function(muDoublePoint // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \ - // expected-error {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \ - // expected-error {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}} int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \ - // expected-error {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} //-----------------------------------------// @@ -814,11 +831,11 @@ int stf_function_bad_3() __attribute__((shared_trylock_function(muDoublePointer) // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \ - // expected-error {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \ - // expected-error {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}} int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \ - // expected-error {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} //-----------------------------------------// @@ -877,11 +894,11 @@ int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2))); // illegal attribute arguments int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \ - // expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \ - // expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'unlock_function' attribute requires arguments that are class type or point to class type}} int uf_function_bad_4() __attribute__((unlock_function(umu))); // \ - // expected-error {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}} int uf_function_bad_1() __attribute__((unlock_function(1))); // \ // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} @@ -951,13 +968,13 @@ int lr_function_8() __attribute__((lock_returned(muPointer))); // illegal attribute arguments int lr_function_bad_1() __attribute__((lock_returned(1))); // \ - // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \ - // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \ - // expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'lock_returned' attribute requires arguments that are class type or point to class type}} int lr_function_bad_4() __attribute__((lock_returned(umu))); // \ - // expected-error {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -1018,13 +1035,13 @@ int le_function_8() __attribute__((locks_excluded(muPointer))); // illegal attribute arguments int le_function_bad_1() __attribute__((locks_excluded(1))); // \ - // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \ - // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \ - // expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'locks_excluded' attribute requires arguments that are class type or point to class type}} int le_function_bad_4() __attribute__((locks_excluded(umu))); // \ - // expected-error {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -1085,13 +1102,13 @@ int elr_function_8() __attribute__((exclusive_locks_required(muPointer))); // illegal attribute arguments int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \ - // expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \ - // expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \ - // expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}} int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \ - // expected-error {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} @@ -1153,13 +1170,13 @@ int slr_function_8() __attribute__((shared_locks_required(muPointer))); // illegal attribute arguments int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \ - // expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \ - // expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \ - // expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} + // expected-warning {{'shared_locks_required' attribute requires arguments that are class type or point to class type}} int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \ - // expected-error {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} + // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}} //-----------------------------------------// @@ -1253,3 +1270,76 @@ public: Mu mu; }; +//------------------------- +// Empty argument lists +//------------------------- + +class __attribute__((lockable)) EmptyArgListsTest { + void lock() __attribute__((exclusive_lock_function())) { } + void unlock() __attribute__((unlock_function())) { } +}; + + +namespace FunctionDefinitionParseTest { +// Test parsing of attributes on function definitions. + +class Foo { +public: + Mu mu_; + void foo1(); + void foo2(Foo *f); +}; + +template <class T> +class Bar { +public: + Mu mu_; + void bar(); +}; + +void Foo::foo1() __attribute__((exclusive_locks_required(mu_))) { } +void Foo::foo2(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { } + +template <class T> +void Bar<T>::bar() __attribute__((exclusive_locks_required(mu_))) { } + +void baz(Foo *f) __attribute__((exclusive_locks_required(f->mu_))) { } + +} // end namespace + + +namespace TestMultiDecl { + +class Foo { +public: + int __attribute__((guarded_by(mu_))) a; + int __attribute__((guarded_by(mu_))) b, c; + +private: + Mu mu_; +}; + + +namespace NestedClassLateDecl { + +class Foo { + class Bar { + int a GUARDED_BY(mu); + int b GUARDED_BY(fooMuStatic); + + void bar() EXCLUSIVE_LOCKS_REQUIRED(mu) { a = 0; } + void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu) { b->a = 0; } + void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; } + + Mu mu; + }; + + int a GUARDED_BY(fooMu); + Mu fooMu; + static Mu fooMuStatic; +}; + +} + +} // end namespace TestMultiDecl + diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index 604a3c0..f36300a 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -76,3 +76,34 @@ void test6() { S (halt()); // expected-warning {{will never be executed}} } + +// Don't warn about unreachable code in template instantiations, as +// they may only be unreachable in that specific instantiation. +void isUnreachable(); + +template <typename T> void test_unreachable_templates() { + T::foo(); + isUnreachable(); // no-warning +} + +struct TestUnreachableA { + static void foo() __attribute__((noreturn)); +}; +struct TestUnreachableB { + static void foo(); +}; + +void test_unreachable_templates_harness() { + test_unreachable_templates<TestUnreachableA>(); + test_unreachable_templates<TestUnreachableB>(); +} + +// Do warn about explict template specializations, as they represent +// actual concrete functions that somebody wrote. + +template <typename T> void funcToSpecialize() {} +template <> void funcToSpecialize<int>() { + halt(); + dead(); // expected-warning {{will never be executed}} +} + diff --git a/test/SemaCXX/warn-unused-parameters.cpp b/test/SemaCXX/warn-unused-parameters.cpp index 75d8dcc..00ce1a9 100644 --- a/test/SemaCXX/warn-unused-parameters.cpp +++ b/test/SemaCXX/warn-unused-parameters.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -verify -std=c++11 %s template<typename T> struct X { T f0(T x); @@ -24,3 +24,11 @@ void test_X(X<int> &x, int i) { x.f4(i); x.f5(i); } + +// Make sure both parameters aren't considered unused. +template <typename... T> +static int test_pack(T... t, T... s) +{ + auto l = [&t...]() { return sizeof...(s); }; + return l(); +} diff --git a/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp index 80298ec..1c0263c 100644 --- a/test/SemaCXX/warn-unused-value.cpp +++ b/test/SemaCXX/warn-unused-value.cpp @@ -30,3 +30,22 @@ void b(Foo f1, Foo f2) { } #undef NOP } + +namespace test2 { + extern "C" { + namespace std { + template<typename T> struct basic_string { + struct X {}; + void method() const { + X* x; + &x[0]; // expected-warning {{expression result unused}} + } + }; + typedef basic_string<char> string; + void func(const std::string& str) { + str.method(); // expected-note {{in instantiation of member function}} + } + } + } +} + diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 5ba1f2a..5827019 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -80,3 +80,45 @@ namespace PR10168 { f<char>(); // expected-note {{here}} } } + +namespace PR11550 { + struct S1 { + S1(); + }; + S1 makeS1(); + void testS1(S1 a) { + // This constructor call can be elided. + S1 x = makeS1(); // expected-warning {{unused variable 'x'}} + + // This one cannot, so no warning. + S1 y; + + // This call cannot, but the constructor is trivial. + S1 z = a; // expected-warning {{unused variable 'z'}} + } + + // The same is true even when we know thet constructor has side effects. + void foo(); + struct S2 { + S2() { + foo(); + } + }; + S2 makeS2(); + void testS2(S2 a) { + S2 x = makeS2(); // expected-warning {{unused variable 'x'}} + S2 y; + S2 z = a; // expected-warning {{unused variable 'z'}} + } + + // Or when the constructor is not declared by the user. + struct S3 { + S1 m; + }; + S3 makeS3(); + void testS3(S3 a) { + S3 x = makeS3(); // expected-warning {{unused variable 'x'}} + S3 y; + S3 z = a; // expected-warning {{unused variable 'z'}} + } +} diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp index 912622f..135e034 100644 --- a/test/SemaCXX/warn-weak-vtables.cpp +++ b/test/SemaCXX/warn-weak-vtables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables -Wweak-template-vtables struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} virtual void f() { } @@ -56,3 +56,23 @@ void uses(Parent &p, Derived &d, VeryDerived &vd) { d.getFoo(); vd.getFoo(); } + +template<typename T> struct TemplVirt { + virtual void f(); +}; + +template class TemplVirt<float>; // expected-warning{{explicit template instantiation 'TemplVirt<float>' will emit a vtable in every translation unit}} + +template<> struct TemplVirt<bool> { + virtual void f(); +}; + +template<> struct TemplVirt<long> { // expected-warning{{'TemplVirt<long>' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} + virtual void f() {} +}; + +void uses(TemplVirt<float>& f, TemplVirt<bool>& b, TemplVirt<long>& l) { + f.f(); + b.f(); + l.f(); +} diff --git a/test/SemaCXX/zero-length-arrays.cpp b/test/SemaCXX/zero-length-arrays.cpp new file mode 100644 index 0000000..05ded4a --- /dev/null +++ b/test/SemaCXX/zero-length-arrays.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/10228639> +class Foo { + ~Foo(); + Foo(const Foo&); +public: + Foo(int); +}; + +class Bar { + int foo_count; + Foo foos[0]; + Foo foos2[0][2]; + Foo foos3[2][0]; + +public: + Bar(): foo_count(0) { } + ~Bar() { } +}; + +void testBar() { + Bar b; + Bar b2(b); + b = b2; +} |