diff options
author | dim <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
commit | 952eddef9aff85b1e92626e89baaf7a360e2ac85 (patch) | |
tree | df8df0b0067b381eab470a3b8f28d14a552a6340 /test/SemaCXX | |
parent | ea266cad53e3d49771fa38103913d3ec7a166694 (diff) | |
download | FreeBSD-src-952eddef9aff85b1e92626e89baaf7a360e2ac85.zip FreeBSD-src-952eddef9aff85b1e92626e89baaf7a360e2ac85.tar.gz |
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):
https://llvm.org/svn/llvm-project/cfe/branches/release_34@197841
Diffstat (limited to 'test/SemaCXX')
186 files changed, 10403 insertions, 474 deletions
diff --git a/test/SemaCXX/Inputs/lit.local.cfg b/test/SemaCXX/Inputs/lit.local.cfg deleted file mode 100644 index e6f55ee..0000000 --- a/test/SemaCXX/Inputs/lit.local.cfg +++ /dev/null @@ -1 +0,0 @@ -config.suffixes = [] diff --git a/test/SemaCXX/Inputs/register.h b/test/SemaCXX/Inputs/register.h new file mode 100644 index 0000000..3c412ee --- /dev/null +++ b/test/SemaCXX/Inputs/register.h @@ -0,0 +1,5 @@ +#pragma GCC system_header +#pragma once + +inline void f() { register int k; } +#define to_int(x) ({ register int n = (x); n; }) diff --git a/test/SemaCXX/Inputs/warn-unused-variables.h b/test/SemaCXX/Inputs/warn-unused-variables.h index 5fac459..56990e0 100644 --- a/test/SemaCXX/Inputs/warn-unused-variables.h +++ b/test/SemaCXX/Inputs/warn-unused-variables.h @@ -7,5 +7,7 @@ class A {}; class B { static A a; + static A b; + static const int x = sizeof(b); }; } diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp index 6a48f36..05037ac 100644 --- a/test/SemaCXX/MicrosoftCompatibility.cpp +++ b/test/SemaCXX/MicrosoftCompatibility.cpp @@ -178,3 +178,19 @@ namespace PR11791 { del((void*)a); // expected-note {{in instantiation of function template specialization}} } } + +namespace IntToNullPtrConv { + struct Foo { + static const int ZERO = 0; + typedef void (Foo::*MemberFcnPtr)(); + }; + + struct Bar { + const Foo::MemberFcnPtr pB; + }; + + Bar g_bar = { (Foo::MemberFcnPtr)Foo::ZERO }; + + template<int N> int *get_n() { return N; } // expected-warning {{expression which evaluates to zero treated as a null pointer constant}} + int *g_nullptr = get_n<0>(); // expected-note {{in instantiation of function template specialization}} +} diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index ab3ff69..c5b45a2 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -167,8 +167,14 @@ void pointer_to_integral_type_conv(char* ptr) { short sh = (short)ptr; ch = (char)ptr; sh = (short)ptr; -} + // These are valid C++. + bool b = (bool)ptr; + b = static_cast<bool>(ptr); + + // This is bad. + b = reinterpret_cast<bool>(ptr); // expected-error {{cast from pointer to smaller type 'bool' loses information}} +} namespace friend_as_a_forward_decl { @@ -333,3 +339,74 @@ void TestSP9() { c3.g(); // Overloaded incdec op operand c3.h(); // Overloaded unary op operand } + +union u { + int *i1; + int &i2; // expected-warning {{union member 'i2' has reference type 'int &', which is a Microsoft extension}} +}; + +// Property getter using reference. +struct SP11 { + __declspec(property(get=GetV)) int V; + int _v; + int& GetV() { return _v; } + void UseV(); + void TakePtr(int *) {} + void TakeRef(int &) {} + void TakeVal(int) {} +}; + +void SP11::UseV() { + TakePtr(&V); + TakeRef(V); + TakeVal(V); +} + +struct StructWithUnnamedMember { + __declspec(property(get=GetV)) int : 10; // expected-error {{anonymous property is not supported}} +}; + +namespace rdar14250378 { + class Bar {}; + + namespace NyNamespace { + class Foo { + public: + Bar* EnsureBar(); + }; + + class Baz : public Foo { + public: + friend class Bar; + }; + + Bar* Foo::EnsureBar() { + return 0; + } + } +} + +// expected-error@+1 {{'sealed' keyword not permitted with interface types}} +__interface InterfaceWithSealed sealed { +}; + +struct SomeBase { + virtual void OverrideMe(); + + // expected-note@+2 {{overridden virtual function is here}} + // expected-warning@+1 {{'sealed' keyword is a Microsoft extension}} + virtual void SealedFunction() sealed; +}; + +// expected-note@+2 {{'SealedType' declared here}} +// expected-warning@+1 {{'sealed' keyword is a Microsoft extension}} +struct SealedType sealed : SomeBase { + // expected-error@+1 {{declaration of 'SealedFunction' overrides a 'sealed' function}} + virtual void SealedFunction(); + + // expected-warning@+1 {{'override' keyword is a C++11 extension}} + virtual void OverrideMe() override; +}; + +// expected-error@+1 {{base 'SealedType' is marked 'sealed'}} +struct InheritFromSealed : SealedType {}; diff --git a/test/SemaCXX/PR10447.cpp b/test/SemaCXX/PR10447.cpp index 5ba74aa..0c57177 100644 --- a/test/SemaCXX/PR10447.cpp +++ b/test/SemaCXX/PR10447.cpp @@ -4,7 +4,7 @@ // PR12223 namespace test1 { namespace N { - extern "C" void f(struct S*); + extern "C" void f_test1(struct S*); void g(S*); } namespace N { @@ -17,7 +17,7 @@ namespace test1 { // PR10447 namespace test2 { extern "C" { - void f(struct Bar*) { } + void f_test2(struct Bar*) { } test2::Bar *ptr; } } diff --git a/test/SemaCXX/PR12778.cpp b/test/SemaCXX/PR12778.cpp new file mode 100644 index 0000000..f4d25f3 --- /dev/null +++ b/test/SemaCXX/PR12778.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void operator delete() throw(void*); // expected-error{{'operator delete' must have at least one parameter}} +void* allocate(int __n) { + return ::operator new(__n); +} + diff --git a/test/SemaCXX/PR9572.cpp b/test/SemaCXX/PR9572.cpp index b475b57..d6dc2e0 100644 --- a/test/SemaCXX/PR9572.cpp +++ b/test/SemaCXX/PR9572.cpp @@ -7,7 +7,7 @@ struct Foo : public Base { // expected-error {{base class 'Base' has private des Foo(); }; struct Bar : public Foo { - Bar() { } // expected-note {{implicit default destructor for 'Foo' first required here}} + Bar() { } // expected-note {{implicit destructor for 'Foo' first required here}} }; struct Baz { Foo f; diff --git a/test/SemaCXX/__try.cpp b/test/SemaCXX/__try.cpp index a0f503a..1c45581 100644 --- a/test/SemaCXX/__try.cpp +++ b/test/SemaCXX/__try.cpp @@ -57,3 +57,23 @@ int main() } return e; } + +namespace PR17584 { +template <typename> +void Except() { + __try { + } __except(true) { + } +} + +template <typename> +void Finally() { + __try { + } __finally { + } +} + +template void Except<void>(); +template void Finally<void>(); + +} diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index e20a890..d7e2d0a 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wabstract-vbase-init #ifndef __GXX_EXPERIMENTAL_CXX0X__ #define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) @@ -250,6 +250,13 @@ namespace test4 { }; } +namespace test5 { + struct A { A(int); virtual ~A() = 0; }; // expected-note {{pure virtual method}} + const A &a = 0; // expected-error {{abstract class}} + void f(const A &a = 0); // expected-error {{abstract class}} + void g() { f(0); } // expected-error {{abstract class}} +} + // PR9247: Crash on invalid in clang::Sema::ActOnFinishCXXMemberSpecification namespace pr9247 { struct A { @@ -273,3 +280,30 @@ namespace pr12658 { foo(C(99)); // expected-error {{allocating an object of abstract class type 'pr12658::C'}}
} } + +namespace pr16659 { + struct A { + A(int); + virtual void x() = 0; // expected-note {{unimplemented pure virtual method 'x' in 'RedundantInit'}} + }; + struct B : virtual A {}; + struct C : B { + C() : A(37) {} + void x() override {} + }; + + struct X { + friend class Z; + private: + X &operator=(const X&); + }; + struct Y : virtual X { // expected-note {{::X' has an inaccessible copy assignment}} + virtual ~Y() = 0; + }; + struct Z : Y {}; // expected-note {{::Y' has a deleted copy assignment}} + void f(Z &a, const Z &b) { a = b; } // expected-error {{copy assignment operator is implicitly deleted}} + + struct RedundantInit : virtual A { + RedundantInit() : A(0) {} // expected-warning {{initializer for virtual base class 'pr16659::A' of abstract class 'RedundantInit' will never be used}} + }; +} diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index 50f2eff..5ccd418 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -26,9 +26,11 @@ private: namespace test1 { class A { private: - class X; // expected-note {{previously declared 'private' here}} + class X; // expected-note {{previously declared 'private' here}} \ + // expected-note {{previous declaration is here}} public: - class X; // expected-error {{'X' redeclared with 'public' access}} + class X; // expected-error {{'X' redeclared with 'public' access}} \ + // expected-warning {{class member cannot be redeclared}} class X {}; }; } @@ -106,3 +108,31 @@ namespace PR15209 { } } } + +namespace PR7434 { + namespace comment0 { + template <typename T> struct X; + namespace N { + class Y { + template<typename T> friend struct X; + int t; // expected-note {{here}} + }; + } + template<typename T> struct X { + X() { (void)N::Y().t; } // expected-error {{private}} + }; + X<char> x; + } + namespace comment2 { + struct X; + namespace N { + class Y { + friend struct X; + int t; // expected-note {{here}} + }; + } + struct X { + X() { (void)N::Y().t; } // expected-error {{private}} + }; + } +} diff --git a/test/SemaCXX/addr-of-overloaded-function-casting.cpp b/test/SemaCXX/addr-of-overloaded-function-casting.cpp index cfd55ee..784c8a0 100644 --- a/test/SemaCXX/addr-of-overloaded-function-casting.cpp +++ b/test/SemaCXX/addr-of-overloaded-function-casting.cpp @@ -4,8 +4,12 @@ void g(); void f(); // expected-note 9{{candidate function}} void f(int); // expected-note 9{{candidate function}} -template<class T> void t(T); // expected-note 6{{candidate function}} -template<class T> void t(T*); // expected-note 6{{candidate function}} +template <class T> +void t(T); // expected-note 3{{candidate function}} \ + // expected-note 3{{candidate template ignored: could not match 'void' against 'int'}} +template <class T> +void t(T *); // expected-note 3{{candidate function}} \ + // expected-note 3{{candidate template ignored: could not match 'void' against 'int'}} template<class T> void u(T); diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp index 096f748..230a1eb 100644 --- a/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -57,11 +57,12 @@ struct B struct C { C &getC() { - return makeAC; // expected-error{{reference to non-static member function must be called}} + return makeAC; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } - C &makeAC(); - const C &makeAC() const; + // FIXME: filter by const so we can unambiguously suggest '()' & point to just the one candidate, probably + C &makeAC(); // expected-note{{possible target for call}} + const C &makeAC() const; // expected-note{{possible target for call}} static void f(); // expected-note{{candidate function}} static void f(int); // expected-note{{candidate function}} @@ -69,6 +70,32 @@ struct C { void g() { int (&fp)() = f; // expected-error{{address of overloaded function 'f' does not match required type 'int ()'}} } + + template<typename T> + void q1(int); // expected-note{{possible target for call}} + template<typename T> + void q2(T t = T()); // expected-note{{possible target for call}} + template<typename T> + void q3(); // expected-note{{possible target for call}} + template<typename T1, typename T2> + void q4(); // expected-note{{possible target for call}} + template<typename T1 = int> // expected-warning{{default template arguments for a function template are a C++11 extension}} + void q5(); // expected-note{{possible target for call}} + + void h() { + // Do not suggest '()' since an int argument is required + q1<int>; // expected-error-re{{reference to non-static member function must be called$}} + // Suggest '()' since there's a default value for the only argument & the + // type argument is already provided + q2<int>; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} + // Suggest '()' since no arguments are required & the type argument is + // already provided + q3<int>; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} + // Do not suggest '()' since another type argument is required + q4<int>; // expected-error-re{{reference to non-static member function must be called$}} + // Suggest '()' since the type parameter has a default value + q5; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} + } }; // PR6886 @@ -208,3 +235,7 @@ namespace test1 { 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')}} } + +template <typename T> class PR16561 { + virtual bool f() { if (f) {} return false; } // expected-error {{reference to non-static member function must be called}} +}; diff --git a/test/SemaCXX/alignment-of-derived-class.cpp b/test/SemaCXX/alignment-of-derived-class.cpp new file mode 100644 index 0000000..28c1fa9 --- /dev/null +++ b/test/SemaCXX/alignment-of-derived-class.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// expected-no-diagnostics + +// Test that the alignment of a empty direct base class is correctly +// inherited by the derived class. + +struct A { +} __attribute__ ((aligned(16))); + +static_assert(__alignof(A) == 16, "A should be aligned to 16 bytes"); + +struct B1 : public A { +}; + +static_assert(__alignof(B1) == 16, "B1 should be aligned to 16 bytes"); + +struct B2 : public A { +} __attribute__ ((aligned(2))); + +static_assert(__alignof(B2) == 16, "B2 should be aligned to 16 bytes"); + +struct B3 : public A { +} __attribute__ ((aligned(4))); + +static_assert(__alignof(B3) == 16, "B3 should be aligned to 16 bytes"); + +struct B4 : public A { +} __attribute__ ((aligned(8))); + +static_assert(__alignof(B4) == 16, "B4 should be aligned to 16 bytes"); + +struct B5 : public A { +} __attribute__ ((aligned(16))); + +static_assert(__alignof(B5) == 16, "B5 should be aligned to 16 bytes"); + +struct B6 : public A { +} __attribute__ ((aligned(32))); + +static_assert(__alignof(B6) == 32, "B6 should be aligned to 32 bytes"); + diff --git a/test/SemaCXX/alignof-sizeof-reference.cpp b/test/SemaCXX/alignof-sizeof-reference.cpp index d76fcf5..3e37d61 100644 --- a/test/SemaCXX/alignof-sizeof-reference.cpp +++ b/test/SemaCXX/alignof-sizeof-reference.cpp @@ -10,8 +10,8 @@ void test() { static_assert(sizeof(char&) == 1, "bad size"); } -void f(); // expected-note{{possible target for call}} -void f(int); // expected-note{{possible target for call}} +int f(); // expected-note{{possible target for call}} +int f(int); // expected-note{{possible target for call}} void g() { sizeof(&f); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} \ // expected-warning{{expression result unused}} diff --git a/test/SemaCXX/alignof.cpp b/test/SemaCXX/alignof.cpp index a9de1ad..f0b89ee 100644 --- a/test/SemaCXX/alignof.cpp +++ b/test/SemaCXX/alignof.cpp @@ -9,7 +9,7 @@ struct S0 { auto test2() -> char(&)[__alignof__(x)]; // expected-error {{invalid application of 'alignof' to a field of a class still being defined}} }; -struct S1; // expected-note 5 {{forward declaration}} +struct S1; // expected-note 6 {{forward declaration}} extern S1 s1; const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}} @@ -50,3 +50,15 @@ struct S4 { static const int test1 = __alignof__(S0::x); auto test2() -> char(&)[__alignof__(x)]; }; + +// Regression test for asking for the alignment of a field within an invalid +// record. +struct S5 { + S1 s; // expected-error {{incomplete type}} + int x; +}; +const int test8 = __alignof__(S5::x); + +long long int test14[2]; + +static_assert(alignof(test14) == 8, "foo"); // expected-warning {{'alignof' applied to an expression is a GNU extension}} diff --git a/test/SemaCXX/ambiguous-conversion-show-overload.cpp b/test/SemaCXX/ambiguous-conversion-show-overload.cpp index 6429651..5cd26fc 100644 --- a/test/SemaCXX/ambiguous-conversion-show-overload.cpp +++ b/test/SemaCXX/ambiguous-conversion-show-overload.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -fno-caret-diagnostics %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fsyntax-only -fshow-overloads=best -fno-caret-diagnostics %s 2>&1 | FileCheck %s struct S { S(void*); S(char*); diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 9c2cf24..fde27b0 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -197,3 +197,12 @@ namespace PR8326 { Foo<int> baz; } + +namespace PR16630 { + struct A { union { int x; float y; }; }; // expected-note {{member is declared here}} + struct B : private A { using A::x; } b; // expected-note 2 {{private}} + void foo () { + b.x = 10; + b.y = 0; // expected-error {{cannot cast 'struct B' to its private base class 'PR16630::A'}} expected-error {{'y' is a private member of 'PR16630::A'}} + } +} diff --git a/test/SemaCXX/ast-print.cpp b/test/SemaCXX/ast-print.cpp index 921f7d8..a1975b4 100644 --- a/test/SemaCXX/ast-print.cpp +++ b/test/SemaCXX/ast-print.cpp @@ -103,6 +103,7 @@ int test11() { struct DefaultArgClass { DefaultArgClass(int a = 1) {} + DefaultArgClass(int a, int b, int c = 1) {} }; struct NoArgClass @@ -124,6 +125,8 @@ struct ConstrWithCleanupsClass // CHECK: test12 // CHECK-NEXT: DefaultArgClass useDefaultArg; // CHECK-NEXT: DefaultArgClass overrideDefaultArg(1); +// CHECK-NEXT: DefaultArgClass(1, 2); +// CHECK-NEXT: DefaultArgClass(1, 2, 3); // CHECK-NEXT: NoArgClass noArg; // CHECK-NEXT: ConstrWithCleanupsClass cwcNoArg; // CHECK-NEXT: ConstrWithCleanupsClass cwcOverrideArg(48); @@ -131,6 +134,8 @@ struct ConstrWithCleanupsClass void test12() { DefaultArgClass useDefaultArg; DefaultArgClass overrideDefaultArg(1); + DefaultArgClass tempWithDefaultArg = DefaultArgClass(1, 2); + DefaultArgClass tempWithExplictArg = DefaultArgClass(1, 2, 3); NoArgClass noArg; ConstrWithCleanupsClass cwcNoArg; ConstrWithCleanupsClass cwcOverrideArg(48); @@ -148,3 +153,14 @@ void test13() { __c11_atomic_load(&i, 0); } + +// CHECK: void test14() { +// CHECK: struct X { +// CHECK: union { +// CHECK: int x; +// CHECK: } x; +// CHECK: }; +// CHECK: } +void test14() { + struct X { union { int x; } x; }; +} diff --git a/test/SemaCXX/attr-aligned.cpp b/test/SemaCXX/attr-aligned.cpp new file mode 100644 index 0000000..4b9c55f --- /dev/null +++ b/test/SemaCXX/attr-aligned.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// expected-no-diagnostics + +typedef struct S1 { char c; } S1 __attribute__((aligned(8))); +static_assert(alignof(S1) == 8, "attribute ignored"); +static_assert(alignof(struct S1) == 1, "attribute applied to original type"); + +typedef struct __attribute__((aligned(8))) S2 { char c; } AS; +static_assert(alignof(S2) == 8, "attribute not propagated"); +static_assert(alignof(struct S2) == 8, "attribute ignored"); + +typedef struct __attribute__((aligned(4))) S3 { + char c; +} S3 __attribute__((aligned(8))); +static_assert(alignof(S3) == 8, "attribute ignored"); +static_assert(alignof(struct S3) == 4, "attribute clobbered"); diff --git a/test/SemaCXX/attr-cleanup-gcc.cpp b/test/SemaCXX/attr-cleanup-gcc.cpp new file mode 100644 index 0000000..daebbe6 --- /dev/null +++ b/test/SemaCXX/attr-cleanup-gcc.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Wgcc-compat + +namespace N { + void c1(int *a) {} +} + +void c2(int *a) {} + +template <typename Ty> +void c3(Ty *a) {} + +void t3() { + int v1 __attribute__((cleanup(N::c1))); // expected-warning {{GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier}} + int v2 __attribute__((cleanup(c2))); + int v3 __attribute__((cleanup(c3<int>))); // expected-warning {{GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier}} +} diff --git a/test/SemaCXX/attr-cleanup.cpp b/test/SemaCXX/attr-cleanup.cpp new file mode 100644 index 0000000..32d1068 --- /dev/null +++ b/test/SemaCXX/attr-cleanup.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-gcc-compat + +namespace N { + void c1(int *a) {} +} + +class C { + static void c2(int *a) {} // expected-note {{implicitly declared private here}} expected-note {{implicitly declared private here}} +}; + +void t1() { + int v1 __attribute__((cleanup(N::c1))); + int v2 __attribute__((cleanup(N::c2))); // expected-error {{no member named 'c2' in namespace 'N'}} + int v3 __attribute__((cleanup(C::c2))); // expected-error {{'c2' is a private member of 'C'}} +} + +class D : public C { + void t2() { + int v1 __attribute__((cleanup(c2))); // expected-error {{'c2' is a private member of 'C'}} + } +}; + +namespace E { + void c3(int *a) {} // expected-note {{candidate function}} + void c3() {} // expected-note {{candidate function}} + void t3() { + int v1 __attribute__((cleanup(c3))); // expected-error {{'c3' is not a single function}} + } +} diff --git a/test/SemaCXX/attr-common.cpp b/test/SemaCXX/attr-common.cpp new file mode 100644 index 0000000..58b3013 --- /dev/null +++ b/test/SemaCXX/attr-common.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +__attribute__((common)) int x; // expected-error {{common attribute is not supported in C++}} diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp index e9276cd..e24e12e 100644 --- a/test/SemaCXX/attr-cxx0x.cpp +++ b/test/SemaCXX/attr-cxx0x.cpp @@ -12,7 +12,7 @@ struct align_member { }; void f(alignas(1) char c) { // expected-error {{'alignas' attribute cannot be applied to a function parameter}} - alignas(1) register char k; // expected-error {{'alignas' attribute cannot be applied to a variable with 'register' storage class}} + alignas(1) register char k; // expected-error {{'alignas' attribute cannot be applied to a variable with 'register' storage class}} expected-warning {{deprecated}} try { } catch (alignas(4) int n) { // expected-error {{'alignas' attribute cannot be applied to a 'catch' variable}} } @@ -44,4 +44,4 @@ static_assert(alignof(align_class_temp_pack_type<short, int, long>) == alignof(l static_assert(alignof(align_class_temp_pack_expr<8, 16, 32>) == 32, "template's alignment is wrong"); static_assert(alignof(outer<int,char>::inner<double,short>) == alignof(int) * alignof(double), "template's alignment is wrong"); -static_assert(alignof(int(int)) >= 1, "alignof(function) not positive"); // expected-warning{{invalid application of 'alignof' to a function type}} +static_assert(alignof(int(int)) >= 1, "alignof(function) not positive"); // expected-error{{invalid application of 'alignof' to a function type}} diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index d09faf3..b3223f3 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -244,3 +244,9 @@ namespace test7 { X *x = new X; // expected-warning{{'operator new' is deprecated}} expected-warning{{'operator delete' is deprecated}} } } + +// rdar://problem/15044218 +typedef struct TDS { +} TDS __attribute__((deprecated)); // expected-note {{'TDS' declared here}} +TDS tds; // expected-warning {{'TDS' is deprecated}} +struct TDS tds2; // no warning, attribute only applies to the typedef. diff --git a/test/SemaCXX/attr-no-sanitize-address.cpp b/test/SemaCXX/attr-no-sanitize-address.cpp index dc4d797..f180349 100644 --- a/test/SemaCXX/attr-no-sanitize-address.cpp +++ b/test/SemaCXX/attr-no-sanitize-address.cpp @@ -9,7 +9,7 @@ void noanal_fun() NO_SANITIZE_ADDRESS; void noanal_fun_args() __attribute__((no_sanitize_address(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'no_sanitize_address' attribute takes no arguments}} int noanal_testfn(int y) NO_SANITIZE_ADDRESS; diff --git a/test/SemaCXX/attr-no-sanitize-memory.cpp b/test/SemaCXX/attr-no-sanitize-memory.cpp index 84acdac..d6eca1b 100644 --- a/test/SemaCXX/attr-no-sanitize-memory.cpp +++ b/test/SemaCXX/attr-no-sanitize-memory.cpp @@ -9,7 +9,7 @@ void noanal_fun() NO_SANITIZE_MEMORY; void noanal_fun_args() __attribute__((no_sanitize_memory(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'no_sanitize_memory' attribute takes no arguments}} int noanal_testfn(int y) NO_SANITIZE_MEMORY; diff --git a/test/SemaCXX/attr-no-sanitize-thread.cpp b/test/SemaCXX/attr-no-sanitize-thread.cpp index 50960c4..d6372bc 100644 --- a/test/SemaCXX/attr-no-sanitize-thread.cpp +++ b/test/SemaCXX/attr-no-sanitize-thread.cpp @@ -9,7 +9,7 @@ void noanal_fun() NO_SANITIZE_THREAD; void noanal_fun_args() __attribute__((no_sanitize_thread(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'no_sanitize_thread' attribute takes no arguments}} int noanal_testfn(int y) NO_SANITIZE_THREAD; diff --git a/test/SemaCXX/attr-print.cpp b/test/SemaCXX/attr-print.cpp index 2e74789..a07eeff 100644 --- a/test/SemaCXX/attr-print.cpp +++ b/test/SemaCXX/attr-print.cpp @@ -16,3 +16,9 @@ void bar() __attribute__((__const)); // FIXME: Print this with correct format and order. // CHECK: void foo1() __attribute__((pure)) __attribute__((noinline)); void foo1() __attribute__((noinline, pure)); + +// CHECK: typedef int Small1 __attribute__((mode(byte))); +typedef int Small1 __attribute__((mode(byte))); + +// CHECK: int small __attribute__((mode(byte))); +int small __attribute__((mode(byte))); diff --git a/test/SemaCXX/attr-selectany.cpp b/test/SemaCXX/attr-selectany.cpp new file mode 100644 index 0000000..0f9776d --- /dev/null +++ b/test/SemaCXX/attr-selectany.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s +// MSVC produces similar diagnostics. + +__declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}} + +__declspec(selectany) int x1 = 1; + +const __declspec(selectany) int x2 = 2; // expected-error{{'selectany' can only be applied to data items with external linkage}} + +extern const __declspec(selectany) int x3 = 3; + +extern const int x4; +const __declspec(selectany) int x4 = 4; + +// MSDN says this is incorrect, but MSVC doesn't diagnose it. +extern __declspec(selectany) int x5; + +static __declspec(selectany) int x6 = 2; // expected-error{{'selectany' can only be applied to data items with external linkage}} + +// FIXME: MSVC accepts this and makes x7 externally visible and comdat, but keep +// it as internal and not weak/linkonce. +static int x7; // expected-note{{previous definition}} +extern __declspec(selectany) int x7; // expected-warning{{attribute declaration must precede definition}} + +int asdf() { return x7; } + +class X { + public: + X(int i) { i++; }; + int i; +}; + +__declspec(selectany) X x(1); diff --git a/test/SemaCXX/attr-used.cpp b/test/SemaCXX/attr-used.cpp new file mode 100644 index 0000000..9bae3ed --- /dev/null +++ b/test/SemaCXX/attr-used.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern char test1[] __attribute__((used)); // expected-warning {{used attribute ignored}} +extern const char test2[] __attribute__((used)); // expected-warning {{used attribute ignored}} +extern const char test3[] __attribute__((used)) = ""; diff --git a/test/SemaCXX/attr-weakref.cpp b/test/SemaCXX/attr-weakref.cpp index f3d7a62..0c3f1d2 100644 --- a/test/SemaCXX/attr-weakref.cpp +++ b/test/SemaCXX/attr-weakref.cpp @@ -32,3 +32,5 @@ int a9 __attribute__((weakref)); // expected-error {{weakref declaration of 'a9 static int a10(); int a10() __attribute__((weakref ("foo"))); + +static int v __attribute__((weakref(a1), alias("foo"))); // expected-error {{'weakref' attribute requires a string}} diff --git a/test/SemaCXX/blocks-1.cpp b/test/SemaCXX/blocks-1.cpp index 02e9cac..e11fd92 100644 --- a/test/SemaCXX/blocks-1.cpp +++ b/test/SemaCXX/blocks-1.cpp @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++11 -// expected-no-diagnostics +// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks -std=c++1y extern "C" int exit(int); @@ -57,3 +56,18 @@ namespace rdar11055105 { foo(a); }; } + +namespace LocalDecls { + void f() { + (void) ^{ + extern int a; // expected-note {{previous}} + extern int b(); // expected-note {{previous}} + }; + } + void g() { + (void) ^{ + extern float a; // expected-error {{different type}} + extern float b(); // expected-error {{cannot be overloaded}} + }; + } +} diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp index f027186..69c0119 100644 --- a/test/SemaCXX/bool.cpp +++ b/test/SemaCXX/bool.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-constant-conversion \ +// RUN: -Wno-deprecated -Wdeprecated-increment-bool %s // Bool literals can be enum values. enum { diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp index 5d61690..69bdfa6 100644 --- a/test/SemaCXX/builtins.cpp +++ b/test/SemaCXX/builtins.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11 typedef const struct __CFString * CFStringRef; #define CFSTR __builtin___CFStringMakeConstantString @@ -24,3 +24,23 @@ void f2() { // pr14895 typedef __typeof(sizeof(int)) size_t; extern "C" void *__builtin_alloca (size_t); + +namespace addressof { + struct S {} s; + static_assert(__builtin_addressof(s) == &s, ""); + + struct T { constexpr T *operator&() const { return nullptr; } int n; } t; + constexpr T *pt = __builtin_addressof(t); + static_assert(&pt->n == &t.n, ""); + + struct U { int n : 5; } u; + int *pbf = __builtin_addressof(u.n); // expected-error {{address of bit-field requested}} + + S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}} +} + +void no_ms_builtins() { + __assume(1); // expected-error {{use of undeclared}} + __noop(1); // expected-error {{use of undeclared}} + __debugbreak(); // expected-error {{use of undeclared}} +} diff --git a/test/SemaCXX/c99.cpp b/test/SemaCXX/c99.cpp index 13918dc..7afcdd5 100644 --- a/test/SemaCXX/c99.cpp +++ b/test/SemaCXX/c99.cpp @@ -2,7 +2,7 @@ void f1(int i[static 5]) { // expected-error{{C99}} } -struct Point { int x; int y; }; +struct Point { int x; int y; int z[]; }; // expected-warning{{flexible array members are a C99 feature}} Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature}} y: 25 }; // expected-warning{{designated initializers are a C99 feature}} \ diff --git a/test/SemaCXX/calling-conv-compat.cpp b/test/SemaCXX/calling-conv-compat.cpp new file mode 100644 index 0000000..2d52386 --- /dev/null +++ b/test/SemaCXX/calling-conv-compat.cpp @@ -0,0 +1,387 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -cxx-abi microsoft -verify -triple i686-pc-win32 %s + +// Pointers to free functions +void free_func_default(); +void __cdecl free_func_cdecl(); +void __stdcall free_func_stdcall(); +void __fastcall free_func_fastcall(); + +typedef void ( *fptr_default)(); +typedef void (__cdecl *fptr_cdecl)(); +typedef void (__stdcall *fptr_stdcall)(); +typedef void (__fastcall *fptr_fastcall)(); + +// expected-note@+4 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}} +// expected-note@+3 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((stdcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((fastcall))' to 'fptr_default' (aka 'void (*)()') for 1st argument}} +void cb_fptr_default(fptr_default ptr); +// expected-note@+4 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}} +// expected-note@+3 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((stdcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (*)() __attribute__((fastcall))' to 'fptr_cdecl' (aka 'void (*)()') for 1st argument}} +void cb_fptr_cdecl(fptr_cdecl ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fptr_stdcall' (aka 'void (*)() __attribute__((stdcall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fptr_stdcall' (aka 'void (*)() __attribute__((stdcall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fptr_stdcall' (aka 'void (*)() __attribute__((stdcall))') for 1st argument}} +void cb_fptr_stdcall(fptr_stdcall ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fptr_fastcall' (aka 'void (*)() __attribute__((fastcall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fptr_fastcall' (aka 'void (*)() __attribute__((fastcall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fptr_fastcall' (aka 'void (*)() __attribute__((fastcall))') for 1st argument}} +void cb_fptr_fastcall(fptr_fastcall ptr); +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'const fptr_default' (aka 'void (*const)()') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'const fptr_default' (aka 'void (*const)()') for 1st argument}} +void cb_fptr_const_default(const fptr_default ptr); + +void call_free_func() { + cb_fptr_default(free_func_default); + cb_fptr_default(free_func_cdecl); + cb_fptr_default(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_default'}} + cb_fptr_default(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_default'}} + cb_fptr_default(&free_func_default); + cb_fptr_default(&free_func_cdecl); + cb_fptr_default(&free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_default'}} + cb_fptr_default(&free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_default'}} + + cb_fptr_cdecl(free_func_default); + cb_fptr_cdecl(free_func_cdecl); + cb_fptr_cdecl(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}} + cb_fptr_cdecl(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}} + cb_fptr_cdecl(&free_func_default); + cb_fptr_cdecl(&free_func_cdecl); + cb_fptr_cdecl(&free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}} + cb_fptr_cdecl(&free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_cdecl'}} + + cb_fptr_stdcall(free_func_default); // expected-error {{no matching function for call to 'cb_fptr_stdcall'}} + cb_fptr_stdcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fptr_stdcall'}} + cb_fptr_stdcall(free_func_stdcall); + cb_fptr_stdcall(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_stdcall'}} + + cb_fptr_fastcall(free_func_default); // expected-error {{no matching function for call to 'cb_fptr_fastcall'}} + cb_fptr_fastcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fptr_fastcall'}} + cb_fptr_fastcall(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_fastcall'}} + cb_fptr_fastcall(free_func_fastcall); + + cb_fptr_const_default(free_func_default); + cb_fptr_const_default(free_func_cdecl); + cb_fptr_const_default(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fptr_const_default'}} + cb_fptr_const_default(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fptr_const_default'}} + +} + +// Pointers to variadic functions +// variadic function can't declared stdcall or fastcall +void free_func_variadic_default(int, ...); +void __cdecl free_func_variadic_cdecl(int, ...); + +typedef void ( *fptr_variadic_default)(int, ...); +typedef void (__cdecl *fptr_variadic_cdecl)(int, ...); + +void cb_fptr_variadic_default(fptr_variadic_default ptr); +void cb_fptr_variadic_cdecl(fptr_variadic_cdecl ptr); + +void call_free_variadic_func() { + cb_fptr_variadic_default(free_func_variadic_default); + cb_fptr_variadic_default(free_func_variadic_cdecl); + cb_fptr_variadic_default(&free_func_variadic_default); + cb_fptr_variadic_default(&free_func_variadic_cdecl); + + cb_fptr_variadic_cdecl(free_func_variadic_default); + cb_fptr_variadic_cdecl(free_func_variadic_cdecl); + cb_fptr_variadic_cdecl(&free_func_variadic_default); + cb_fptr_variadic_cdecl(&free_func_variadic_cdecl); +} + +// References to functions +typedef void ( &fref_default)(); +typedef void (__cdecl &fref_cdecl)(); +typedef void (__stdcall &fref_stdcall)(); +typedef void (__fastcall &fref_fastcall)(); + +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fref_default' (aka 'void (&)()') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fref_default' (aka 'void (&)()') for 1st argument}} +void cb_fref_default(fref_default ptr); +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fref_cdecl' (aka 'void (&)()') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fref_cdecl' (aka 'void (&)()') for 1st argument}} +void cb_fref_cdecl(fref_cdecl ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fref_stdcall' (aka 'void (&)() __attribute__((stdcall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fref_stdcall' (aka 'void (&)() __attribute__((stdcall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((fastcall))' to 'fref_stdcall' (aka 'void (&)() __attribute__((stdcall))') for 1st argument}} +void cb_fref_stdcall(fref_stdcall ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void ()' to 'fref_fastcall' (aka 'void (&)() __attribute__((fastcall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void () __attribute__((cdecl))' to 'fref_fastcall' (aka 'void (&)() __attribute__((fastcall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void () __attribute__((stdcall))' to 'fref_fastcall' (aka 'void (&)() __attribute__((fastcall))') for 1st argument}} +void cb_fref_fastcall(fref_fastcall ptr); + +void call_free_func_ref() { + cb_fref_default(free_func_default); + cb_fref_default(free_func_cdecl); + cb_fref_default(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fref_default'}} + cb_fref_default(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fref_default'}} + + cb_fref_cdecl(free_func_default); + cb_fref_cdecl(free_func_cdecl); + cb_fref_cdecl(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fref_cdecl'}} + cb_fref_cdecl(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fref_cdecl'}} + + cb_fref_stdcall(free_func_default); // expected-error {{no matching function for call to 'cb_fref_stdcall'}} + cb_fref_stdcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fref_stdcall'}} + cb_fref_stdcall(free_func_stdcall); + cb_fref_stdcall(free_func_fastcall); // expected-error {{no matching function for call to 'cb_fref_stdcall'}} + + cb_fref_fastcall(free_func_default); // expected-error {{no matching function for call to 'cb_fref_fastcall'}} + cb_fref_fastcall(free_func_cdecl); // expected-error {{no matching function for call to 'cb_fref_fastcall'}} + cb_fref_fastcall(free_func_stdcall); // expected-error {{no matching function for call to 'cb_fref_fastcall'}} + cb_fref_fastcall(free_func_fastcall); +} + +// References to variadic functions +// variadic function can't declared stdcall or fastcall +typedef void ( &fref_variadic_default)(int, ...); +typedef void (__cdecl &fref_variadic_cdecl)(int, ...); + +void cb_fref_variadic_default(fptr_variadic_default ptr); +void cb_fref_variadic_cdecl(fptr_variadic_cdecl ptr); + +void call_free_variadic_func_ref() { + cb_fref_variadic_default(free_func_variadic_default); + cb_fref_variadic_default(free_func_variadic_cdecl); + + cb_fref_variadic_cdecl(free_func_variadic_default); + cb_fref_variadic_cdecl(free_func_variadic_cdecl); +} + +// Pointers to members +namespace NonVariadic { + +struct A { + void member_default(); + void __cdecl member_cdecl(); + void __thiscall member_thiscall(); +}; + +struct B : public A { +}; + +struct C { + void member_default(); + void __cdecl member_cdecl(); + void __thiscall member_thiscall(); +}; + +typedef void ( A::*memb_a_default)(); +typedef void (__cdecl A::*memb_a_cdecl)(); +typedef void (__thiscall A::*memb_a_thiscall)(); +typedef void ( B::*memb_b_default)(); +typedef void (__cdecl B::*memb_b_cdecl)(); +typedef void (__thiscall B::*memb_b_thiscall)(); +typedef void ( C::*memb_c_default)(); +typedef void (__cdecl C::*memb_c_cdecl)(); +typedef void (__thiscall C::*memb_c_thiscall)(); + +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (NonVariadic::A::*)() __attribute__((thiscall))') for 1st argument}} +void cb_memb_a_default(memb_a_default ptr); +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (NonVariadic::A::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (NonVariadic::A::*)() __attribute__((cdecl))') for 1st argument}} +void cb_memb_a_cdecl(memb_a_cdecl ptr); +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (NonVariadic::A::*)() __attribute__((thiscall))') for 1st argument}} +void cb_memb_a_thiscall(memb_a_thiscall ptr); +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (NonVariadic::B::*)() __attribute__((thiscall))') for 1st argument}} +void cb_memb_b_default(memb_b_default ptr); +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (NonVariadic::B::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (NonVariadic::B::*)() __attribute__((cdecl))') for 1st argument}} +void cb_memb_b_cdecl(memb_b_cdecl ptr); +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (NonVariadic::B::*)() __attribute__((thiscall))') for 1st argument}} +void cb_memb_b_thiscall(memb_b_thiscall ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +void cb_memb_c_default(memb_c_default ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (NonVariadic::C::*)() __attribute__((cdecl))') for 1st argument}} +void cb_memb_c_cdecl(memb_c_cdecl ptr); +// expected-note@+3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (NonVariadic::C::*)() __attribute__((thiscall))') for 1st argument}} +void cb_memb_c_thiscall(memb_c_thiscall ptr); + +void call_member() { + cb_memb_a_default(&A::member_default); + cb_memb_a_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_a_default'}} + cb_memb_a_default(&A::member_thiscall); + + cb_memb_a_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_a_cdecl'}} + cb_memb_a_cdecl(&A::member_cdecl); + cb_memb_a_cdecl(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_a_cdecl'}} + + cb_memb_a_thiscall(&A::member_default); + cb_memb_a_thiscall(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_a_thiscall'}} + cb_memb_a_thiscall(&A::member_thiscall); +} + +void call_member_inheritance() { + cb_memb_b_default(&A::member_default); + cb_memb_b_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_b_default'}} + cb_memb_b_default(&A::member_thiscall); + cb_memb_c_default(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_default'}} + cb_memb_c_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_default'}} + cb_memb_c_default(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_c_default'}} + + cb_memb_b_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_b_cdecl'}} + cb_memb_b_cdecl(&A::member_cdecl); + cb_memb_b_cdecl(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_b_cdecl'}} + cb_memb_c_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}} + cb_memb_c_cdecl(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}} + cb_memb_c_cdecl(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}} + + cb_memb_b_thiscall(&A::member_default); + cb_memb_b_thiscall(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_b_thiscall'}} + cb_memb_b_thiscall(&A::member_thiscall); + cb_memb_c_thiscall(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_thiscall'}} + cb_memb_c_thiscall(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_thiscall'}} + cb_memb_c_thiscall(&A::member_thiscall); // expected-error {{no matching function for call to 'cb_memb_c_thiscall'}} +} +} // end namespace NonVariadic + +namespace Variadic { +struct A { + void member_default(int, ...); + void __cdecl member_cdecl(int, ...); + void __thiscall member_thiscall(int, ...); // expected-error {{variadic function cannot use thiscall calling convention}} +}; + +struct B : public A { +}; + +struct C { + void member_default(int, ...); + void __cdecl member_cdecl(int, ...); +}; + +typedef void ( A::*memb_a_default)(int, ...); +typedef void (__cdecl A::*memb_a_cdecl)(int, ...); +typedef void ( B::*memb_b_default)(int, ...); +typedef void (__cdecl B::*memb_b_cdecl)(int, ...); +typedef void ( C::*memb_c_default)(int, ...); +typedef void (__cdecl C::*memb_c_cdecl)(int, ...); + +void cb_memb_a_default(memb_a_default ptr); +void cb_memb_a_cdecl(memb_a_cdecl ptr); +void cb_memb_b_default(memb_b_default ptr); +void cb_memb_b_cdecl(memb_b_cdecl ptr); +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_default' (aka 'void (Variadic::C::*)(int, ...)') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (Variadic::C::*)(int, ...)') for 1st argument}} +void cb_memb_c_default(memb_c_default ptr); +// expected-note@+2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (Variadic::C::*)(int, ...) __attribute__((cdecl))') for 1st argument}} +// expected-note@+1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (Variadic::C::*)(int, ...) __attribute__((cdecl))') for 1st argument}} +void cb_memb_c_cdecl(memb_c_cdecl ptr); + +void call_member() { + cb_memb_a_default(&A::member_default); + cb_memb_a_default(&A::member_cdecl); + + cb_memb_a_cdecl(&A::member_default); + cb_memb_a_cdecl(&A::member_cdecl); +} + +void call_member_inheritance() { + cb_memb_b_default(&A::member_default); + cb_memb_b_default(&A::member_cdecl); + cb_memb_c_default(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_default'}} + cb_memb_c_default(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_default'}} + + cb_memb_b_cdecl(&A::member_default); + cb_memb_b_cdecl(&A::member_cdecl); + cb_memb_c_cdecl(&A::member_default); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}} + cb_memb_c_cdecl(&A::member_cdecl); // expected-error {{no matching function for call to 'cb_memb_c_cdecl'}} +} +} // end namespace Variadic + +namespace MultiChunkDecls { + +// Try to test declarators that have multiple DeclaratorChunks. +struct A { + void __thiscall member_thiscall(int); +}; + +void (A::*return_mptr(short))(int) { + return &A::member_thiscall; +} + +void (A::*(*return_fptr_mptr(char))(short))(int) { + return return_mptr; +} + +typedef void (A::*mptr_t)(int); +mptr_t __stdcall return_mptr_std(short) { + return &A::member_thiscall; +} + +void (A::*(*return_fptr_std_mptr(char))(short))(int) { + return return_mptr_std; // expected-error {{cannot initialize return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) __attribute__((thiscall))' with an lvalue of type 'mptr_t (short) __attribute__((stdcall))'}} +} + +void call_return() { + A o; + void (A::*(*fptr)(short))(int) = return_fptr_mptr('a'); + void (A::*mptr)(int) = fptr(1); + (o.*mptr)(2); +} + +} // end namespace MultiChunkDecls + +namespace MemberPointers { + +struct A { + void __thiscall method_thiscall(); + void __cdecl method_cdecl(); + void __stdcall method_stdcall(); + void __fastcall method_fastcall(); +}; + +void ( A::*mp1)() = &A::method_thiscall; +void (__cdecl A::*mp2)() = &A::method_cdecl; +void (__stdcall A::*mp3)() = &A::method_stdcall; +void (__fastcall A::*mp4)() = &A::method_fastcall; + +// Use a typedef to form the member pointer and verify that cdecl is adjusted. +typedef void ( fun_default)(); +typedef void (__cdecl fun_cdecl)(); +typedef void (__stdcall fun_stdcall)(); +typedef void (__fastcall fun_fastcall)(); + +// FIXME: Adjust cdecl to thiscall when forming a member pointer. +//fun_default A::*td1 = &A::method_thiscall; +fun_cdecl A::*td2 = &A::method_cdecl; +fun_stdcall A::*td3 = &A::method_stdcall; +fun_fastcall A::*td4 = &A::method_fastcall; + +// Round trip the function type through a template, and verify that only cdecl +// gets adjusted. +template<typename Fn> struct X { + typedef Fn A::*p; +}; + +// FIXME: Adjust cdecl to thiscall when forming a member pointer. +//X<void ()>::p tmpl1 = &A::method_thiscall; +//X<void __cdecl ()>::p tmpl2 = &A::method_thiscall; +X<void __stdcall ()>::p tmpl3 = &A::method_stdcall; +X<void __fastcall ()>::p tmpl4 = &A::method_fastcall; + +} // end namespace MemberPointers + +// Test that lambdas that capture nothing convert to cdecl function pointers. +namespace Lambdas { + +void pass_fptr_cdecl (void (__cdecl *fp)()); +void pass_fptr_stdcall (void (__stdcall *fp)()); // expected-note {{candidate function not viable}} +void pass_fptr_fastcall(void (__fastcall *fp)()); // expected-note {{candidate function not viable}} + +void conversion_to_fptr() { + pass_fptr_cdecl ([]() { } ); + pass_fptr_stdcall ([]() { } ); // expected-error {{no matching function for call}} + pass_fptr_fastcall([]() { } ); // expected-error {{no matching function for call}} +} + +} diff --git a/test/SemaCXX/captured-statements.cpp b/test/SemaCXX/captured-statements.cpp index dbb18a7..5fb686c 100644 --- a/test/SemaCXX/captured-statements.cpp +++ b/test/SemaCXX/captured-statements.cpp @@ -164,3 +164,10 @@ void test_capture_variadic() { (void)captured_sum(1, 2, 3); // OK (void)captured_sum(1, 2, 3, 4, 5); // OK } + +void test_capture_with_attributes() { + [[]] // expected-error {{an attribute list cannot appear here}} + #pragma clang __debug captured + { + } +} diff --git a/test/SemaCXX/cast-conversion.cpp b/test/SemaCXX/cast-conversion.cpp index 270f968..4d5abfd 100644 --- a/test/SemaCXX/cast-conversion.cpp +++ b/test/SemaCXX/cast-conversion.cpp @@ -16,8 +16,7 @@ struct B { // expected-note 3 {{candidate constructor (the implicit copy constru int main () { B(10); // expected-error {{no matching conversion for functional-style cast from 'int' to 'B'}} (B)10; // expected-error {{no matching conversion for C-style cast from 'int' to 'B'}} - static_cast<B>(10); // expected-error {{no matching conversion for static_cast from 'int' to 'B'}} \\ - // expected-warning {{expression result unused}} + static_cast<B>(10); // expected-error {{no matching conversion for static_cast from 'int' to 'B'}} } template<class T> @@ -65,3 +64,18 @@ void *intToPointer4() { void *intToPointer5(long l) { return (void*)l; } + +struct AmbiguousCast { + operator int(); // expected-note {{candidate function}} + operator unsigned int(); // expected-note {{candidate function}} +}; +long long AmbiguousCastFunc(AmbiguousCast& a) { + return static_cast<long long>(a); // expected-error {{ambiguous conversion for static_cast from 'AmbiguousCast' to 'long long'}} +} + +namespace PR16680 { + void f(int (*__pf)()); + int g() { + f(reinterpret_cast<int>(0.0f)); // expected-error {{reinterpret_cast from 'float' to 'int' is not allowed}} + } +} diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp index 2cdca82..8344e6f 100644 --- a/test/SemaCXX/class-base-member-init.cpp +++ b/test/SemaCXX/class-base-member-init.cpp @@ -98,3 +98,13 @@ namespace rdar13185264 { union { void *a; }; }; } + +namespace PR16596 { + class A { public: virtual ~A(); }; + typedef const A Foo; + void Apply(Foo processor); + struct Bar : public Foo {}; + void Fetch() { + Apply(Bar()); + } +} diff --git a/test/SemaCXX/class-layout.cpp b/test/SemaCXX/class-layout.cpp index f2ff9fc..64c8ceb 100644 --- a/test/SemaCXX/class-layout.cpp +++ b/test/SemaCXX/class-layout.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 // expected-no-diagnostics #define SA(n, p) int a##n[(p) ? 1 : -1] @@ -103,3 +104,469 @@ struct H { G g; }; SA(0, sizeof(H) == 24); } + +namespace PR16537 { +namespace test1 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test2 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11 __attribute__((aligned(16))); + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test3 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test4 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + char may_go_into_tail_padding; + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test5 { + struct pod_in_11_only { + private: + long long x; + }; + + struct pod_in_11_only2 { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + pod_in_11_only2 two; + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + char may_go_into_tail_padding; + }; + SA(0, sizeof(might_use_tail_padding) == 32); +} + +namespace test6 { + struct pod_in_11_only { + private: + long long x; + }; + + struct pod_in_11_only2 { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + pod_in_11_only2 two; + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + char may_go_into_tail_padding; + }; + SA(0, sizeof(might_use_tail_padding) == 32); +} + +namespace test7 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + pod_in_11_only pod12; + char tail_padding; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 24); +} + +namespace test8 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct another_layer { + tail_padded_pod_in_11_only pod; + char padding; + }; + + struct might_use_tail_padding : public another_layer { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 24); +} + +namespace test9 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct another_layer : tail_padded_pod_in_11_only { + }; + + struct might_use_tail_padding : public another_layer { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test10 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char b; + }; + + struct C { + pod_in_11_only c; + char cpad; + }; + + struct D { + char d; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + }; + + SA(0, sizeof(might_use_tail_padding) == 32); +} + +namespace test11 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char b_pre; + pod_in_11_only b; + char bpad; + }; + + struct C { + char c_pre; + pod_in_11_only c; + char cpad; + }; + + struct D { + char d_pre; + pod_in_11_only d; + char dpad; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char m; + }; + + SA(0, sizeof(might_use_tail_padding) == 88); +} + +namespace test12 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a __attribute__((aligned(128))); + }; + + struct B { + char bpad; + }; + + struct C { + char cpad; + }; + + struct D { + char dpad; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 128); +} + +namespace test13 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + }; + + struct C { + char c_pre; + pod_in_11_only c; + char cpad; + }; + + struct D { + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 40); +} + +namespace test14 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct might_use_tail_padding : public A { + struct { + int : 0; + } x; + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test15 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct might_use_tail_padding : public A { + struct { + char a:1; + char b:2; + char c:2; + char d:2; + char e:1; + } x; + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test16 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char bpod; + pod_in_11_only b; + char bpad; + }; + + struct C : public A, public B { + }; + + struct D : public C { + }; + + struct might_use_tail_padding : public D { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 40); +} + +namespace test17 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a __attribute__((aligned(512))); + }; + + struct B { + char bpad; + pod_in_11_only foo; + char btail; + }; + + struct C { + char cpad; + }; + + struct D { + char dpad; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char a; + }; + SA(0, sizeof(might_use_tail_padding) == 512); +} + +namespace test18 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char bpod; + pod_in_11_only b; + char bpad; + }; + + struct A1 { + pod_in_11_only a; + char apad; + }; + + struct B1 { + char bpod; + pod_in_11_only b; + char bpad; + }; + + struct C : public A, public B { + }; + + struct D : public A1, public B1 { + }; + + struct E : public D, public C { + }; + + struct F : public E { + }; + + struct might_use_tail_padding : public F { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 80); +} +} // namespace PR16537 diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp index 972a79b..636f584 100644 --- a/test/SemaCXX/class.cpp +++ b/test/SemaCXX/class.cpp @@ -126,12 +126,8 @@ struct S // Don't crash on this bogus code. namespace pr6629 { - // TODO: most of these errors are spurious template<class T1, class T2> struct foo : - 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<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}} { }; template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}} diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp index feb1ccb..8214f78 100644 --- a/test/SemaCXX/compare.cpp +++ b/test/SemaCXX/compare.cpp @@ -355,3 +355,70 @@ void test9(int x) { }; (void)((E)x == 1); } + +namespace templates { + template<class T> T max(); + + template<> constexpr int max<int>() { return 2147483647; }; + + template<typename T> + bool less_than_max(short num, T value) { + const T vmax = max<T>(); + return (vmax >= num); // no warning + } + + template<typename T> + bool less_than_max(short num) { + // This should trigger one warning on the template pattern, and not a + // warning per specialization. + return num < max<int>(); // expected-warning{{comparison of constant 2147483647 with expression of type 'short' is always true}} + } + + void test10(short num, int x) { + less_than_max(num, x); + less_than_max<int>(num); + less_than_max<long>(num); + less_than_max<short>(num); + } + + template<typename T> + inline bool less_than_zero(T num, T value) { + return num < 0; // no warning + } + + template<typename T> + inline bool less_than_zero(unsigned num) { + // This should trigger one warning on the template pattern, and not a + // warning per specialization. + return num < 0; // expected-warning{{comparison of unsigned expression < 0 is always false}} + } + + void test11(unsigned num) { + less_than_zero(num, num); + less_than_zero<int>(num); + less_than_zero<long>(num); + less_than_zero<short>(num); + } + + template<unsigned n> bool compare(unsigned k) { return k >= n; } + + void test12() { + compare<0>(42); + } + + struct A { static int x; }; + struct B { static int x; }; + typedef A otherA; + + template <typename T> + void testx() { + if (A::x == T::x && // no warning + A::x == otherA::x) // expected-warning{{self-comparison always evaluates to true}} + return; + } + + void test13() { + testx<A>(); + testx<B>(); + } +} diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp index 719a850..1381968 100644 --- a/test/SemaCXX/complex-overload.cpp +++ b/test/SemaCXX/complex-overload.cpp @@ -42,9 +42,15 @@ void test_promote_or_convert2(float _Complex fc) { int *cp = promote_or_convert2(fc); } -char *promote_or_convert3(int _Complex); -int *promote_or_convert3(long _Complex); +char *promote_or_convert3(int _Complex); // expected-note {{candidate}} +int *promote_or_convert3(long _Complex); // expected-note {{candidate}} void test_promote_or_convert3(short _Complex sc) { - char *cp = promote_or_convert3(sc); + char *cp1 = promote_or_convert3(sc); + char *cp2 = promote_or_convert3(1i); + int *cp3 = promote_or_convert3(1il); + int *cp4 = promote_or_convert3(1ill); // expected-error {{ambiguous}} } + +char &convert4(short _Complex); +char &test_convert4 = convert4(1i); diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp index 595747e..3fc6150 100644 --- a/test/SemaCXX/compound-literal.cpp +++ b/test/SemaCXX/compound-literal.cpp @@ -76,3 +76,13 @@ namespace brace_initializers { (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}} } } + +// This doesn't necessarily need to be an error, but CodeGen can't handle it +// at the moment. +int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a compile-time constant}} + +// Make sure we accept this. (Not sure if we actually should... but we do +// at the moment.) +template<unsigned> struct Value { }; +template<typename T> +int &check_narrowed(Value<sizeof((T){1.1})>); diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 692aaef..5abee4a 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -81,6 +81,8 @@ void test() i1 ? test() : test(); i1 = i1 ? throw 0 : 0; i1 = i1 ? 0 : throw 0; + i1 = i1 ? (throw 0) : 0; + i1 = i1 ? 0 : (throw 0); i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}} i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}} (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}} diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp index 62851f8..1fe350d 100644 --- a/test/SemaCXX/const-cast.cpp +++ b/test/SemaCXX/const-cast.cpp @@ -38,6 +38,7 @@ char ***good_const_cast_test(ccvpcvpp var) f *fpp = const_cast<f*>(&fp); int const A::* const A::*icapcap = 0; int A::* A::* iapap = const_cast<int A::* A::*>(icapcap); + (void)const_cast<A&&>(A()); // expected-warning {{C++11}} return var4; } @@ -60,5 +61,6 @@ short *bad_const_cast_test(char const *volatile *const volatile *var) f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} void (A::*mfn)() = 0; (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}} + (void)const_cast<int&&>(0); // expected-error {{const_cast from rvalue to reference type 'int &&'}} expected-warning {{C++11}} return **var3; } diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 09a9cb5..6724be7 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment +// RUN: %clang_cc1 -triple i686-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment namespace StaticAssertFoldTest { @@ -79,6 +79,11 @@ constexpr int **n6 = const_cast<int**>(&n3); constexpr int n7 = **n5; constexpr int n8 = **n6; +// const_cast from prvalue to xvalue. +struct A { int n; }; +constexpr int n9 = (const_cast<A&&>(A{123})).n; +static_assert(n9 == 123, ""); + } namespace TemplateArgumentConversion { @@ -339,6 +344,46 @@ static_assert(!same(4, 4), ""); static_assert(same(n, n), ""); static_assert(sameTemporary(9), ""); +struct A { int &&r; }; +struct B { A &&a1; A &&a2; }; + +constexpr B b1 { { 1 }, { 2 } }; // expected-note {{temporary created here}} +static_assert(&b1.a1 != &b1.a2, ""); +static_assert(&b1.a1.r != &b1.a2.r, ""); // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}} + +constexpr B &&b2 { { 3 }, { 4 } }; // expected-note {{temporary created here}} +static_assert(&b1 != &b2, ""); +static_assert(&b1.a1 != &b2.a1, ""); // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}} + +constexpr thread_local B b3 { { 1 }, { 2 } }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} +void foo() { + constexpr static B b1 { { 1 }, { 2 } }; // ok + constexpr thread_local B b2 { { 1 }, { 2 } }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} + constexpr B b3 { { 1 }, { 2 } }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} +} + +constexpr B &&b4 = ((1, 2), 3, 4, B { {10}, {{20}} }); // expected-warning 4{{unused}} +static_assert(&b4 != &b2, ""); + +// Proposed DR: copy-elision doesn't trigger lifetime extension. +constexpr B b5 = B{ {0}, {0} }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} + +namespace NestedNonStatic { + // Proposed DR: for a reference constant expression to refer to a static + // storage duration temporary, that temporary must itself be initialized + // by a constant expression (a core constant expression is not enough). + struct A { int &&r; }; + struct B { A &&a; }; + constexpr B a = { A{0} }; // ok + constexpr B b = { A(A{0}) }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}} +} + +namespace FakeInitList { + struct init_list_3_ints { const int (&x)[3]; }; + struct init_list_2_init_list_3_ints { const init_list_3_ints (&x)[2]; }; + constexpr init_list_2_init_list_3_ints ils = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } }; +} + } constexpr int strcmp_ce(const char *p, const char *q) { @@ -572,7 +617,7 @@ 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}} +constexpr const E &e1 = E(); // 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(); @@ -729,15 +774,22 @@ static_assert(&ok2 == pok2, ""); static_assert((Base2*)(Derived*)(Base*)pb1 == pok2, ""); static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, ""); -constexpr Base *nullB = 42 - 6 * 7; // expected-warning {{expression which evaluates to zero treated as a null pointer constant of type 'Class::Base *const'}} +// Core issue 903: we do not perform constant evaluation when checking for a +// null pointer in C++11. Just check for an integer literal with value 0. +constexpr Base *nullB = 42 - 6 * 7; // expected-error {{cannot initialize a variable of type 'Class::Base *const' with an rvalue of type 'int'}} +constexpr Base *nullB1 = 0; static_assert((Bottom*)nullB == 0, ""); static_assert((Derived*)nullB == 0, ""); static_assert((void*)(Bottom*)nullB == (void*)(Derived*)nullB, ""); -Base * nullB2 = '\0'; // expected-warning {{expression which evaluates to zero treated as a null pointer constant of type 'Class::Base *'}} -Base * nullB3 = (0); -// We suppress the warning in unevaluated contexts to workaround some gtest -// behavior. Once this becomes an error this isn't a problem anymore. -static_assert(nullB == (1 - 1), ""); +Base *nullB2 = '\0'; // expected-error {{cannot initialize a variable of type 'Class::Base *' with an rvalue of type 'char'}} +Base *nullB3 = (0); +Base *nullB4 = false; // expected-error {{cannot initialize a variable of type 'Class::Base *' with an rvalue of type 'bool'}} +Base *nullB5 = ((0ULL)); +Base *nullB6 = 0.; // expected-error {{cannot initialize a variable of type 'Class::Base *' with an rvalue of type 'double'}} +enum Null { kNull }; +Base *nullB7 = kNull; // expected-error {{cannot initialize a variable of type 'Class::Base *' with an rvalue of type 'Class::Null'}} +static_assert(nullB1 == (1 - 1), ""); // expected-error {{comparison between pointer and integer}} + namespace ConversionOperators { @@ -778,21 +830,26 @@ namespace Temporaries { struct S { constexpr S() {} constexpr int f() const; + constexpr int g() const; }; struct T : S { constexpr T(int n) : S(), n(n) {} int n; }; constexpr int S::f() const { - // '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; + return static_cast<const T*>(this)->n; // expected-note {{cannot cast}} +} +constexpr int S::g() const { + // FIXME: Better diagnostic for this. + return this->*(int(S::*))&T::n; // expected-note {{subexpression}} } // 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(S().f(), ""); // expected-error {{constant expression}} expected-note {{in call to '&Temporaries::S()->f()'}} +static_assert(S().g(), ""); // expected-error {{constant expression}} expected-note {{in call to '&Temporaries::S()->g()'}} static_assert(T(3).f() == 3, ""); +static_assert(T(4).g() == 4, ""); constexpr int f(const S &s) { return static_cast<const T&>(s).n; @@ -1138,6 +1195,31 @@ namespace ComplexConstexpr { static_assert(&__imag test6 == &__real test6 + 1, ""); } +// _Atomic(T) is exactly like T for the purposes of constant expression +// evaluation.. +namespace Atomic { + constexpr _Atomic int n = 3; + + struct S { _Atomic(double) d; }; + constexpr S s = { 0.5 }; + constexpr double d1 = s.d; + constexpr double d2 = n; + constexpr _Atomic double d3 = n; + + constexpr _Atomic(int) n2 = d3; + static_assert(d1 == 0.5, ""); + static_assert(d3 == 3.0, ""); + + namespace PR16056 { + struct TestVar { + _Atomic(int) value; + constexpr TestVar(int value) : value(value) {} + }; + constexpr TestVar testVar{-1}; + static_assert(testVar.value == -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; } @@ -1252,8 +1334,23 @@ struct Wrap { 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}} +// The temporary here has static storage duration, so we can bind a constexpr +// reference to it. +constexpr const int &i = 1; +constexpr const int j = i; +static_assert(j == 1, ""); + +// The temporary here is not const, so it can't be read outside the expression +// in which it was created (per the C++14 rules, which we use to avoid a C++11 +// defect). +constexpr int &&k = 1; // expected-note {{temporary created here}} +constexpr const int l = k; // expected-error {{constant expression}} expected-note {{read of temporary}} + +void f() { + // The temporary here has automatic storage duration, so we can't bind a + // constexpr reference to it. + constexpr const int &i = 1; // expected-error {{constant expression}} expected-note 2{{temporary}} +} } @@ -1503,3 +1600,266 @@ namespace PR15884 { // expected-note@-3 {{pointer to temporary is not a constant expression}} // expected-note@-4 {{temporary created here}} } + +namespace AfterError { + // FIXME: Suppress the 'no return statements' diagnostic if the body is invalid. + constexpr int error() { // expected-error {{no return statement}} + return foobar; // expected-error {{undeclared identifier}} + } + constexpr int k = error(); // expected-error {{must be initialized by a constant expression}} +} + +namespace std { + typedef decltype(sizeof(int)) size_t; + + template <class _E> + class initializer_list + { + const _E* __begin_; + size_t __size_; + + constexpr 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; + + constexpr initializer_list() : __begin_(nullptr), __size_(0) {} + + constexpr size_t size() const {return __size_;} + constexpr const _E* begin() const {return __begin_;} + constexpr const _E* end() const {return __begin_ + __size_;} + }; +} + +namespace InitializerList { + constexpr int sum(const int *b, const int *e) { + return b != e ? *b + sum(b+1, e) : 0; + } + constexpr int sum(std::initializer_list<int> ints) { + return sum(ints.begin(), ints.end()); + } + static_assert(sum({1, 2, 3, 4, 5}) == 15, ""); +} + +namespace StmtExpr { + struct A { int k; }; + void f() { + static_assert(({ const int x = 5; x * 3; }) == 15, ""); // expected-warning {{extension}} + constexpr auto a = ({ A(); }); // expected-warning {{extension}} + } + constexpr int g(int k) { + return ({ // expected-warning {{extension}} + const int x = k; + x * x; + }); + } + static_assert(g(123) == 15129, ""); + constexpr int h() { // expected-error {{never produces a constant}} + return ({ // expected-warning {{extension}} + return 0; // expected-note {{not supported}} + 1; + }); + } +} + +namespace VirtualFromBase { + struct S1 { + virtual int f() const; + }; + struct S2 { + virtual int f(); + }; + template <typename T> struct X : T { + constexpr X() {} + double d = 0.0; + constexpr int f() { return sizeof(T); } // expected-warning {{will not be implicitly 'const' in C++1y}} + }; + + // Virtual f(), not OK. + constexpr X<X<S1>> xxs1; + constexpr X<S1> *p = const_cast<X<X<S1>>*>(&xxs1); + static_assert(p->f() == sizeof(X<S1>), ""); // expected-error {{constant expression}} expected-note {{virtual function call}} + + // Non-virtual f(), OK. + constexpr X<X<S2>> xxs2; + constexpr X<S2> *q = const_cast<X<X<S2>>*>(&xxs2); + static_assert(q->f() == sizeof(S2), ""); +} + +namespace ConstexprConstructorRecovery { + class X { + public: + enum E : short { + headers = 0x1, + middlefile = 0x2, + choices = 0x4 + }; + constexpr X() noexcept {}; + protected: + E val{0}; // expected-error {{cannot initialize a member subobject of type 'ConstexprConstructorRecovery::X::E' with an rvalue of type 'int'}} + }; + constexpr X x{}; +} + +namespace Lifetime { + void f() { + constexpr int &n = n; // expected-error {{constant expression}} expected-note {{use of reference outside its lifetime}} expected-warning {{not yet bound to a value}} + constexpr int m = m; // expected-error {{constant expression}} expected-note {{read of object outside its lifetime}} + } + + constexpr int &get(int &&n) { return n; } + struct S { + int &&r; // expected-note 2{{declared here}} + int &s; + int t; + constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning {{temporary}} + constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning {{temporary}} expected-note {{read of object outside its lifetime}} + }; + constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor + constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}} +} + +namespace Bitfields { + struct A { + bool b : 1; + unsigned u : 5; + int n : 5; + bool b2 : 3; + unsigned u2 : 74; // expected-warning {{exceeds the size of its type}} + int n2 : 81; // expected-warning {{exceeds the size of its type}} + }; + + constexpr A a = { false, 33, 31, false, 0xffffffff, 0x7fffffff }; // expected-warning 2{{truncation}} + static_assert(a.b == 0 && a.u == 1 && a.n == -1 && a.b2 == 0 && + a.u2 + 1 == 0 && a.n2 == 0x7fffffff, + "bad truncation of bitfield values"); + + struct B { + int n : 3; + constexpr B(int k) : n(k) {} + }; + static_assert(B(3).n == 3, ""); + static_assert(B(4).n == -4, ""); + static_assert(B(7).n == -1, ""); + static_assert(B(8).n == 0, ""); + static_assert(B(-1).n == -1, ""); + static_assert(B(-8889).n == -1, ""); + + namespace PR16755 { + struct X { + int x : 1; + constexpr static int f(int x) { + return X{x}.x; + } + }; + static_assert(X::f(3) == -1, "3 should truncate to -1"); + } +} + +namespace ZeroSizeTypes { + constexpr int (*p1)[0] = 0, (*p2)[0] = 0; + constexpr int k = p2 - p1; + // expected-error@-1 {{constexpr variable 'k' must be initialized by a constant expression}} + // expected-note@-2 {{subtraction of pointers to type 'int [0]' of zero size}} + + int arr[5][0]; + constexpr int f() { // expected-error {{never produces a constant expression}} + return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int [0]' of zero size}} + } +} + +namespace BadDefaultInit { + template<int N> struct X { static const int n = N; }; + + struct A { // expected-note {{subexpression}} + int k = X<A().k>::n; // expected-error {{defaulted default constructor of 'A' cannot be used}} expected-error {{not a constant expression}} expected-note {{in call to 'A()'}} + }; + + // FIXME: The "constexpr constructor must initialize all members" diagnostic + // here is bogus (we discard the k(k) initializer because the parameter 'k' + // has been marked invalid). + struct B { // expected-note 2{{candidate}} + constexpr B( // expected-error {{must initialize all members}} expected-note {{candidate}} + int k = X<B().k>::n) : // expected-error {{no matching constructor}} + k(k) {} + int k; // expected-note {{not initialized}} + }; +} + +namespace NeverConstantTwoWays { + // If we see something non-constant but foldable followed by something + // non-constant and not foldable, we want the first diagnostic, not the + // second. + constexpr int f(int n) { // expected-error {{never produces a constant expression}} + return (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}} + 1 / 0 : // expected-warning {{division by zero}} + 0; + } + + // FIXME: We should diagnose the cast to long here, not the division by zero. + constexpr int n = // expected-error {{must be initialized by a constant expression}} + (int *)(long)&n == &n ? + 1 / 0 : // expected-warning {{division by zero}} expected-note {{division by zero}} + 0; +} + +namespace PR17800 { + struct A { + constexpr int operator()() const { return 0; } + }; + template <typename ...T> constexpr int sink(T ...) { + return 0; + } + template <int ...N> constexpr int run() { + return sink(A()() + N ...); + } + constexpr int k = run<1, 2, 3>(); +} + +namespace BuiltinStrlen { + constexpr const char *a = "foo\0quux"; + constexpr char b[] = "foo\0quux"; + constexpr int f() { return 'u'; } + constexpr char c[] = { 'f', 'o', 'o', 0, 'q', f(), 'u', 'x', 0 }; + + static_assert(__builtin_strlen("foo") == 3, ""); + static_assert(__builtin_strlen("foo\0quux") == 3, ""); + static_assert(__builtin_strlen("foo\0quux" + 4) == 4, ""); + + constexpr bool check(const char *p) { + return __builtin_strlen(p) == 3 && + __builtin_strlen(p + 1) == 2 && + __builtin_strlen(p + 2) == 1 && + __builtin_strlen(p + 3) == 0 && + __builtin_strlen(p + 4) == 4 && + __builtin_strlen(p + 5) == 3 && + __builtin_strlen(p + 6) == 2 && + __builtin_strlen(p + 7) == 1 && + __builtin_strlen(p + 8) == 0; + } + + static_assert(check(a), ""); + static_assert(check(b), ""); + static_assert(check(c), ""); + + constexpr int over1 = __builtin_strlen(a + 9); // expected-error {{constant expression}} expected-note {{one-past-the-end}} + constexpr int over2 = __builtin_strlen(b + 9); // expected-error {{constant expression}} expected-note {{one-past-the-end}} + constexpr int over3 = __builtin_strlen(c + 9); // expected-error {{constant expression}} expected-note {{one-past-the-end}} + + constexpr int under1 = __builtin_strlen(a - 1); // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} + constexpr int under2 = __builtin_strlen(b - 1); // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} + constexpr int under3 = __builtin_strlen(c - 1); // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} + + // FIXME: The diagnostic here could be better. + constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. + constexpr int bad = __builtin_strlen(d); // expected-error {{constant expression}} expected-note {{one-past-the-end}} +} diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp index 60ec820..521526d 100644 --- a/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/test/SemaCXX/constant-expression-cxx1y.cpp @@ -128,10 +128,10 @@ constexpr int namespace_alias() { namespace assign { constexpr int a = 0; const int b = 0; - int c = 0; // expected-note 2{{here}} + int c = 0; // expected-note {{here}} constexpr void set(const int &a, int b) { - const_cast<int&>(a) = b; // expected-note 2{{constant expression cannot modify an object that is visible outside that expression}} + const_cast<int&>(a) = b; // expected-note 3{{constant expression cannot modify an object that is visible outside that expression}} } constexpr int wrap(int a, int b) { set(a, b); @@ -140,7 +140,7 @@ namespace assign { static_assert((set(a, 1), a) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(a, 1)'}} static_assert((set(b, 1), b) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(b, 1)'}} - static_assert((set(c, 1), c) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + static_assert((set(c, 1), c) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(c, 1)'}} static_assert(wrap(a, 1) == 1, ""); static_assert(wrap(b, 1) == 1, ""); @@ -250,11 +250,12 @@ namespace lifetime { } namespace const_modify { - constexpr int modify(int &n) { return n = 1; } // expected-note {{modification of object of const-qualified type 'const int'}} + constexpr int modify(int &n) { return n = 1; } // expected-note 2 {{modification of object of const-qualified type 'const int'}} constexpr int test1() { int k = 0; return modify(k); } - constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note {{in call}} + constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note 2 {{in call}} static_assert(test1() == 1, ""); static_assert(test2() == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} + constexpr int i = test2(); // expected-error {{constant expression}} expected-note {{in call}} } namespace null { @@ -334,6 +335,99 @@ namespace incdec { static_assert(incr(0) == 101, ""); } +namespace compound_assign { + constexpr bool test_int() { + int a = 3; + a += 6; + if (a != 9) return false; + a -= 2; + if (a != 7) return false; + a *= 3; + if (a != 21) return false; + if (&(a /= 10) != &a) return false; + if (a != 2) return false; + a <<= 3; + if (a != 16) return false; + a %= 6; + if (a != 4) return false; + a >>= 1; + if (a != 2) return false; + a ^= 10; + if (a != 8) return false; + a |= 5; + if (a != 13) return false; + a &= 14; + if (a != 12) return false; + return true; + } + static_assert(test_int(), ""); + + constexpr bool test_float() { + float f = 123.; + f *= 2; + if (f != 246.) return false; + if ((f -= 0.5) != 245.5) return false; + if (f != 245.5) return false; + f /= 0.5; + if (f != 491.) return false; + f += -40; + if (f != 451.) return false; + return true; + } + static_assert(test_float(), ""); + + constexpr bool test_ptr() { + int arr[123] = {}; + int *p = arr; + if ((p += 4) != &arr[4]) return false; + if (p != &arr[4]) return false; + p += -1; + if (p != &arr[3]) return false; + if ((p -= -10) != &arr[13]) return false; + if (p != &arr[13]) return false; + p -= 11; + if (p != &arr[2]) return false; + return true; + } + static_assert(test_ptr(), ""); + + template<typename T> + constexpr bool test_overflow() { + T a = 1; + while (a != a / 2) + a *= 2; // expected-note {{value 2147483648 is outside the range}} expected-note {{ 9223372036854775808 }} expected-note {{floating point arithmetic produces an infinity}} + return true; + } + + static_assert(test_overflow<int>(), ""); // expected-error {{constant}} expected-note {{call}} + static_assert(test_overflow<unsigned>(), ""); // ok, unsigned overflow is defined + static_assert(test_overflow<short>(), ""); // ok, short is promoted to int before multiplication + static_assert(test_overflow<unsigned short>(), ""); // ok + static_assert(test_overflow<unsigned long long>(), ""); // ok + static_assert(test_overflow<long long>(), ""); // expected-error {{constant}} expected-note {{call}} + static_assert(test_overflow<float>(), ""); // expected-error {{constant}} expected-note {{call}} + + constexpr short test_promotion(short k) { + short s = k; + s *= s; + return s; + } + static_assert(test_promotion(100) == 10000, ""); + static_assert(test_promotion(200) == -25536, ""); + static_assert(test_promotion(256) == 0, ""); + + constexpr const char *test_bounds(const char *p, int o) { + return p += o; // expected-note {{element 5 of}} expected-note {{element -1 of}} expected-note {{element 1000 of}} + } + static_assert(test_bounds("foo", 0)[0] == 'f', ""); + static_assert(test_bounds("foo", 3)[0] == 0, ""); + static_assert(test_bounds("foo", 4)[-3] == 'o', ""); + static_assert(test_bounds("foo" + 4, -4)[0] == 'f', ""); + static_assert(test_bounds("foo", 5) != 0, ""); // expected-error {{constant}} expected-note {{call}} + static_assert(test_bounds("foo", -1) != 0, ""); // expected-error {{constant}} expected-note {{call}} + static_assert(test_bounds("foo", 1000) != 0, ""); // expected-error {{constant}} expected-note {{call}} +} + namespace loops { constexpr int fib_loop(int a) { int f_k = 0, f_k_plus_one = 1; @@ -407,7 +501,7 @@ namespace loops { int arr[] = { 1, 2, 3, 4, 5 }; int sum = 0; for (int x : arr) - sum = sum + x; + sum += x; return sum; } static_assert(range_for() == 15, ""); @@ -450,10 +544,370 @@ namespace loops { array<int, 5> arr { 1, 2, 3, 4, 5 }; int sum = 0; for (int k : arr) { - sum = sum + k; + sum += k; if (sum > 8) break; } return sum; } static_assert(range_for_2() == 10, ""); } + +namespace assignment_op { + struct A { + constexpr A() : n(5) {} + int n; + struct B { + int k = 1; + union U { + constexpr U() : y(4) {} + int x; + int y; + } u; + } b; + }; + constexpr bool testA() { + A a, b; + a.n = 7; + a.b.u.y = 5; + b = a; + return b.n == 7 && b.b.u.y == 5 && b.b.k == 1; + } + static_assert(testA(), ""); + + struct B { + bool assigned = false; + constexpr B &operator=(const B&) { + assigned = true; + return *this; + } + }; + struct C : B { + B b; + int n = 5; + }; + constexpr bool testC() { + C c, d; + c.n = 7; + d = c; + c.n = 3; + return d.n == 7 && d.assigned && d.b.assigned; + } + static_assert(testC(), ""); +} + +namespace switch_stmt { + constexpr int f(char k) { + bool b = false; + int z = 6; + switch (k) { + return -1; + case 0: + if (false) { + case 1: + z = 1; + for (; b;) { + return 5; + while (0) + case 2: return 2; + case 7: z = 7; + do case 6: { + return z; + if (false) + case 3: return 3; + case 4: z = 4; + } while (1); + case 5: b = true; + case 9: z = 9; + } + return z; + } else if (false) case 8: z = 8; + else if (false) { + case 10: + z = -10; + break; + } + else z = 0; + return z; + default: + return -1; + } + return -z; + } + static_assert(f(0) == 0, ""); + static_assert(f(1) == 1, ""); + static_assert(f(2) == 2, ""); + static_assert(f(3) == 3, ""); + static_assert(f(4) == 4, ""); + static_assert(f(5) == 5, ""); + static_assert(f(6) == 6, ""); + static_assert(f(7) == 7, ""); + static_assert(f(8) == 8, ""); + static_assert(f(9) == 9, ""); + static_assert(f(10) == 10, ""); + + // Check that we can continue an outer loop from within a switch. + constexpr bool contin() { + for (int n = 0; n != 10; ++n) { + switch (n) { + case 0: + ++n; + continue; + case 1: + return false; + case 2: + return true; + } + } + return false; + } + static_assert(contin(), ""); + + constexpr bool switch_into_for() { + int n = 0; + switch (n) { + for (; n == 1; ++n) { + return n == 1; + case 0: ; + } + } + return false; + } + static_assert(switch_into_for(), ""); + + constexpr void duff_copy(char *a, const char *b, int n) { + switch ((n - 1) % 8 + 1) { + for ( ; n; n = (n - 1) & ~7) { + case 8: a[n-8] = b[n-8]; + case 7: a[n-7] = b[n-7]; + case 6: a[n-6] = b[n-6]; + case 5: a[n-5] = b[n-5]; + case 4: a[n-4] = b[n-4]; + case 3: a[n-3] = b[n-3]; + case 2: a[n-2] = b[n-2]; + case 1: a[n-1] = b[n-1]; + } + case 0: ; + } + } + + constexpr bool test_copy(const char *str, int n) { + char buffer[16] = {}; + duff_copy(buffer, str, n); + for (int i = 0; i != sizeof(buffer); ++i) + if (buffer[i] != (i < n ? str[i] : 0)) + return false; + return true; + } + static_assert(test_copy("foo", 0), ""); + static_assert(test_copy("foo", 1), ""); + static_assert(test_copy("foo", 2), ""); + static_assert(test_copy("hello world", 0), ""); + static_assert(test_copy("hello world", 7), ""); + static_assert(test_copy("hello world", 8), ""); + static_assert(test_copy("hello world", 9), ""); + static_assert(test_copy("hello world", 10), ""); + static_assert(test_copy("hello world", 10), ""); +} + +namespace deduced_return_type { + constexpr auto f() { return 0; } + template<typename T> constexpr auto g(T t) { return t; } + static_assert(f() == 0, ""); + static_assert(g(true), ""); +} + +namespace modify_temporary_during_construction { + struct A { int &&temporary; int x; int y; }; + constexpr int f(int &r) { r *= 9; return r - 12; } + // FIXME: The 'uninitialized' warning here is bogus. + constexpr A a = { 6, f(a.temporary), a.temporary }; // expected-warning {{uninitialized}} expected-note {{temporary created here}} + static_assert(a.x == 42, ""); + static_assert(a.y == 54, ""); + constexpr int k = a.temporary++; // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}} +} + +namespace std { + typedef decltype(sizeof(int)) size_t; + + template <class _E> + class initializer_list + { + const _E* __begin_; + size_t __size_; + + constexpr 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; + + constexpr initializer_list() : __begin_(nullptr), __size_(0) {} + + constexpr size_t size() const {return __size_;} + constexpr const _E* begin() const {return __begin_;} + constexpr const _E* end() const {return __begin_ + __size_;} + }; +} + +namespace InitializerList { + constexpr int sum(std::initializer_list<int> ints) { + int total = 0; + for (int n : ints) total += n; + return total; + } + static_assert(sum({1, 2, 3, 4, 5}) == 15, ""); +} + +namespace StmtExpr { + constexpr int f(int k) { + switch (k) { + case 0: + return 0; + + ({ + case 1: // expected-note {{not supported}} + return 1; + }); + } + } + static_assert(f(1) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} + + constexpr int g() { // expected-error {{never produces a constant}} + return ({ int n; n; }); // expected-note {{object of type 'int' is not initialized}} + } + + // FIXME: We should handle the void statement expression case. + constexpr int h() { // expected-error {{never produces a constant}} + ({ if (true) {} }); // expected-note {{not supported}} + return 0; + } +} + +namespace VirtualFromBase { + struct S1 { + virtual int f() const; + }; + struct S2 { + virtual int f(); + }; + template <typename T> struct X : T { + constexpr X() {} + double d = 0.0; + constexpr int f() { return sizeof(T); } + }; + + // Non-virtual f(), OK. + constexpr X<X<S1>> xxs1; + constexpr X<S1> *p = const_cast<X<X<S1>>*>(&xxs1); + static_assert(p->f() == sizeof(S1), ""); + + // Virtual f(), not OK. + constexpr X<X<S2>> xxs2; + constexpr X<S2> *q = const_cast<X<X<S2>>*>(&xxs2); + static_assert(q->f() == sizeof(X<S2>), ""); // expected-error {{constant expression}} expected-note {{virtual function call}} +} + +namespace Lifetime { + constexpr int &get(int &&r) { return r; } + constexpr int f() { + int &r = get(123); + return r; // expected-note {{read of object outside its lifetime}} + } + static_assert(f() == 123, ""); // expected-error {{constant expression}} expected-note {{in call}} + + constexpr int g() { + int *p = 0; + { + int n = 0; + p = &n; + n = 42; + } + *p = 123; // expected-note {{assignment to object outside its lifetime}} + return *p; + } + static_assert(g() == 42, ""); // expected-error {{constant expression}} expected-note {{in call}} + + constexpr int h(int n) { + int *p[4] = {}; + int &&r = 1; + p[0] = &r; + while (int a = 1) { + p[1] = &a; + for (int b = 1; int c = 1; ) { + p[2] = &b, p[3] = &c; + break; + } + break; + } + *p[n] = 0; // expected-note 3{{assignment to object outside its lifetime}} + return *p[n]; + } + static_assert(h(0) == 0, ""); // ok, lifetime-extended + static_assert(h(1) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(h(2) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} + static_assert(h(3) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} + + // FIXME: This function should be treated as non-constant. + constexpr void lifetime_versus_loops() { + int *p = 0; + for (int i = 0; i != 2; ++i) { + int *q = p; + int n = 0; + p = &n; + if (i) + // This modifies the 'n' from the previous iteration of the loop outside + // its lifetime. + ++*q; + } + } + static_assert((lifetime_versus_loops(), true), ""); +} + +namespace Bitfields { + struct A { + bool b : 3; + int n : 4; + unsigned u : 5; + }; + constexpr bool test() { + A a {}; + a.b += 2; + --a.n; + --a.u; + a.n = -a.n * 3; + return a.b == false && a.n == 3 && a.u == 31; + } + static_assert(test(), ""); +} + +namespace PR17615 { + struct A { + int &&r; + constexpr A(int &&r) : r(static_cast<int &&>(r)) {} + constexpr A() : A(0) { + (void)+r; // expected-note {{outside its lifetime}} + } + }; + constexpr int k = A().r; // expected-error {{constant expression}} expected-note {{in call to}} +} + +namespace PR17331 { + template<typename T, unsigned int N> + constexpr T sum(const T (&arr)[N]) { + T result = 0; + for (T i : arr) + result += i; + return result; + } + + constexpr int ARR[] = { 1, 2, 3, 4, 5 }; + static_assert(sum(ARR) == 15, ""); +} diff --git a/test/SemaCXX/constexpr-backtrace-limit.cpp b/test/SemaCXX/constexpr-backtrace-limit.cpp index 9c40eed..64a26cf 100644 --- a/test/SemaCXX/constexpr-backtrace-limit.cpp +++ b/test/SemaCXX/constexpr-backtrace-limit.cpp @@ -1,4 +1,4 @@ -// 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 +// RUN: not %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)' @@ -6,21 +6,21 @@ // 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 +// RUN: not %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 +// RUN: not %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 +// RUN: not %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)' diff --git a/test/SemaCXX/constexpr-duffs-device.cpp b/test/SemaCXX/constexpr-duffs-device.cpp new file mode 100644 index 0000000..f77d989 --- /dev/null +++ b/test/SemaCXX/constexpr-duffs-device.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++1y -verify %s + +// expected-no-diagnostics +constexpr void copy(const char *from, unsigned long count, char *to) { + unsigned long n = (count + 7) / 8; + switch(count % 8) { + case 0: do { *to++ = *from++; + case 7: *to++ = *from++; + case 6: *to++ = *from++; + case 5: *to++ = *from++; + case 4: *to++ = *from++; + case 3: *to++ = *from++; + case 2: *to++ = *from++; + case 1: *to++ = *from++; + } while(--n > 0); + } +} + +struct S { + char stuff[14]; + constexpr S() : stuff{} { + copy("Hello, world!", 14, stuff); + } +}; + +constexpr bool streq(const char *a, const char *b) { + while (*a && *a == *b) ++a, ++b; + return *a == *b; +} + +static_assert(streq(S().stuff, "Hello, world!"), "should be same"); +static_assert(!streq(S().stuff, "Something else"), "should be different"); diff --git a/test/SemaCXX/constexpr-steps.cpp b/test/SemaCXX/constexpr-steps.cpp new file mode 100644 index 0000000..f7967ee --- /dev/null +++ b/test/SemaCXX/constexpr-steps.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++1y -fsyntax-only -verify %s -DMAX=1234 -fconstexpr-steps 1234 +// RUN: %clang_cc1 -std=c++1y -fsyntax-only -verify %s -DMAX=10 -fconstexpr-steps 10 +// RUN: %clang -std=c++1y -fsyntax-only -Xclang -verify %s -DMAX=12345 -fconstexpr-steps=12345 + +// This takes a total of n + 4 steps according to our current rules: +// - One for the compound-statement that is the function body +// - One for the 'for' statement +// - One for the 'int k = 0;' statement +// - One for each of the n evaluations of the compound-statement in the 'for' body +// - One for the 'return' statemnet +constexpr bool steps(int n) { + for (int k = 0; k != n; ++k) {} + return true; // expected-note {{step limit}} +} + +static_assert(steps((MAX - 4)), ""); // ok +static_assert(steps((MAX - 3)), ""); // expected-error {{constant}} expected-note{{call}} diff --git a/test/SemaCXX/constexpr-turing.cpp b/test/SemaCXX/constexpr-turing.cpp index 07c04ef..75aefbf 100644 --- a/test/SemaCXX/constexpr-turing.cpp +++ b/test/SemaCXX/constexpr-turing.cpp @@ -33,24 +33,24 @@ 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 : + return state == halt ? 0 : 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. +// 3-state busy beaver. S(bb3) = 21. constexpr State bb3[] = { - { { true, R, 1 }, { true, L, 2 } }, - { { true, L, 0 }, { true, R, 1 } }, - { { true, L, 1 }, { true, R, halt } } + { { true, R, 1 }, { true, R, halt } }, + { { true, L, 1 }, { false, R, 2 } }, + { { true, L, 2 }, { true, L, 0 } } }; -static_assert(run(bb3, Tape(), 0) == 14, ""); +static_assert(run(bb3, Tape(), 0) == 21, ""); -// 4-state busy beaver. 108 steps. +// 4-state busy beaver. S(bb4) = 107. 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, ""); +static_assert(run(bb4, Tape(), 0) == 107, ""); diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp index d137bd8..e5b7db5 100644 --- a/test/SemaCXX/constexpr-value-init.cpp +++ b/test/SemaCXX/constexpr-value-init.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify +// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++11 -fsyntax-only -verify struct A { constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{outside its lifetime}} diff --git a/test/SemaCXX/conversion-delete-expr.cpp b/test/SemaCXX/conversion-delete-expr.cpp index 0f298a8..a1ddeb2 100644 --- a/test/SemaCXX/conversion-delete-expr.cpp +++ b/test/SemaCXX/conversion-delete-expr.cpp @@ -2,11 +2,11 @@ // Test1 struct B { - operator char *(); // expected-note {{candidate function}} + operator char *(); // expected-note {{conversion to pointer type}} }; struct D : B { - operator int *(); // expected-note {{candidate function}} + operator int *(); // expected-note {{conversion to pointer type}} }; void f (D d) @@ -30,11 +30,11 @@ void f1 (D1 d) // Test3 struct B2 { - operator const int *(); // expected-note {{candidate function}} + operator const int *(); // expected-note {{conversion to pointer type}} }; struct D2 : B2 { - operator int *(); // expected-note {{candidate function}} + operator int *(); // expected-note {{conversion to pointer type}} }; void f2 (D2 d) @@ -44,11 +44,11 @@ void f2 (D2 d) // Test4 struct B3 { - operator const int *(); // expected-note {{candidate function}} + operator const int *(); // expected-note {{conversion to pointer type}} }; struct A3 { - operator const int *(); // expected-note {{candidate function}} + operator const int *(); // expected-note {{conversion to pointer type}} }; struct D3 : A3, B3 { @@ -78,7 +78,7 @@ void f5(X1 x) { delete x; } // OK. In selecting a conversion to pointer functio // Test7 struct Base { - operator int*(); + operator int*(); }; struct Derived : Base { @@ -87,9 +87,9 @@ struct Derived : Base { }; void foo6(const Derived cd, Derived d) { - // overload resolution selects Derived::operator int*() const; - delete cd; - delete d; + // overload resolution selects Derived::operator int*() const; + delete cd; + delete d; } // Test8 @@ -104,6 +104,6 @@ struct DD : BB { void foo7 (DD d) { - // OK. In selecting a conversion to pointer function, template convesions are skipped. - delete d; + // OK. In selecting a conversion to pointer function, template convesions are skipped. + delete d; } diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 6fca050..7eaed54 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s class X { public: operator bool(); @@ -11,6 +11,8 @@ public: float g() { return operator float(); // expected-error{{use of undeclared 'operator float'}} } + + static operator short(); // expected-error{{conversion function must be a non-static member function}} }; operator int(); // expected-error{{conversion function must be a non-static member function}} diff --git a/test/SemaCXX/conversion-incomplete-type.cpp b/test/SemaCXX/conversion-incomplete-type.cpp new file mode 100644 index 0000000..ebedd04 --- /dev/null +++ b/test/SemaCXX/conversion-incomplete-type.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct string {}; + +class StringPiece; // expected-note {{forward declaration of 'StringPiece'}} \ + // expected-note {{forward declaration of 'StringPiece'}} + +struct Test { + void expectStringPiece(const StringPiece& blah) {}; // expected-note {{passing argument to parameter 'blah' here}} + + void test(const string& s) { + expectStringPiece(s); // expected-error {{no viable conversion from 'const string' to incomplete type 'const StringPiece'}} + } +}; + +struct TestStatic { + static void expectStringPiece(const StringPiece& blah) {}; // expected-note {{passing argument to parameter 'blah' here}} + + static void test(const string& s) { + expectStringPiece(s); // expected-error {{no viable conversion from 'const string' to incomplete type 'const StringPiece'}} + } +}; + diff --git a/test/SemaCXX/crashes.cpp b/test/SemaCXX/crashes.cpp index f5682bd..0b15bb0 100644 --- a/test/SemaCXX/crashes.cpp +++ b/test/SemaCXX/crashes.cpp @@ -171,3 +171,50 @@ namespace test3 { int& x = dimenX.*sides; } } + +namespace pr16964 { + template<typename> struct bs { + bs(); + static int* member(); + member(); // expected-error{{C++ requires a type specifier for all declarations}} + static member(); // expected-error{{C++ requires a type specifier for all declarations}} + static int* member(int); + }; + + template<typename T> bs<T>::bs() { member; } + + bs<int> test() { + return bs<int>(); + } +} + +namespace pr12791 { + template<class _Alloc> class allocator {}; + template<class _CharT> struct char_traits; + struct input_iterator_tag {}; + struct forward_iterator_tag : public input_iterator_tag {}; + + template<typename _CharT, typename _Traits, typename _Alloc> struct basic_string { + struct _Alloc_hider : _Alloc {}; + mutable _Alloc_hider _M_dataplus; + template<class _InputIterator> basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a = _Alloc()); + template<class _InIterator> static _CharT* _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, input_iterator_tag); + template<class _FwdIterator> static _CharT* _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a, forward_iterator_tag); + static _CharT* _S_construct(size_type __req, _CharT __c, const _Alloc& __a); // expected-error{{unknown type name 'size_type'}} + }; + + template<typename _CharT, typename _Traits, typename _Alloc> + template<typename _InputIterator> + basic_string<_CharT, _Traits, _Alloc>:: basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a) + : _M_dataplus(_S_construct(__beg, __end, __a), __a) {} + + template<typename _CharT, typename _Traits = char_traits<_CharT>, typename _Alloc = allocator<_CharT> > struct basic_stringbuf { + typedef _CharT char_type; + typedef basic_string<char_type, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + __string_type str() const {__string_type((char_type*)0,(char_type*)0);} + }; + + template class basic_stringbuf<char>; +} + diff --git a/test/SemaCXX/cxx0x-class.cpp b/test/SemaCXX/cxx0x-class.cpp index 074591e..2b1338f9 100644 --- a/test/SemaCXX/cxx0x-class.cpp +++ b/test/SemaCXX/cxx0x-class.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-error=static-float-init %s +// RUN: %clang_cc1 -Wno-uninitialized -fsyntax-only -verify -std=c++11 -Wno-error=static-float-init %s int vs = 0; diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp index 123008a..ffbd20f 100644 --- a/test/SemaCXX/cxx0x-compat.cpp +++ b/test/SemaCXX/cxx0x-compat.cpp @@ -1,4 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++11-compat -verify %s + +#if __cplusplus < 201103L namespace N { template<typename T> void f(T) {} // expected-note 2{{here}} @@ -37,3 +40,9 @@ void h(size_t foo, size_t bar) { #define _x + 1 char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}} + +#else + +auto init_capture = [a(0)] {}; // expected-warning {{initialized lambda captures are incompatible with C++ standards before C++1y}} + +#endif diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp index f53ac6d..0e9a97d 100644 --- a/test/SemaCXX/cxx0x-initializer-aggregates.cpp +++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp @@ -4,7 +4,6 @@ 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 { @@ -20,25 +19,25 @@ namespace aggregate { }; 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}} + S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; + S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; + S s3{ 1, 2, 3, 4, 5, 6 }; + S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; + S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; } 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}} + new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; + new S{ 1, 2, 3, 4, 5, 6 }; + new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; + new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; } 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}} + (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; + (void) S{ 1, 2, 3, 4, 5, 6 }; + (void) S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; + (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; } struct String { diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp index 283c32a..9096c8a 100644 --- a/test/SemaCXX/cxx0x-initializer-references.cpp +++ b/test/SemaCXX/cxx0x-initializer-references.cpp @@ -36,10 +36,10 @@ namespace reference { }; void call() { - void f(const int&); + one f(const int&); f({1}); - void g(int&); // expected-note {{passing argument}} + one g(int&); // expected-note {{passing argument}} g({1}); // expected-error {{cannot bind to an initializer list temporary}} int i = 0; g({i}); @@ -97,3 +97,24 @@ namespace b7891773 { int g(const ptr &); int k = g({ f<int> }); } + +namespace inner_init { + struct A { int n; }; + struct B { A &&r; }; + B b1 { 0 }; // expected-error {{reference to type 'inner_init::A' could not bind to an rvalue of type 'int'}} + B b2 { { 0 } }; + B b3 { { { 0 } } }; // expected-warning {{braces around scalar init}} + + struct C { C(int); }; + struct D { C &&r; }; + D d1 { 0 }; // ok, 0 implicitly converts to C + D d2 { { 0 } }; // ok, { 0 } calls C(0) + D d3 { { { 0 } } }; // ok, { { 0 } } calls C({ 0 }) + D d4 { { { { 0 } } } }; // expected-warning {{braces around scalar init}} + + struct E { explicit E(int); }; // expected-note 2{{here}} + struct F { E &&r; }; + F f1 { 0 }; // expected-error {{could not bind to an rvalue of type 'int'}} + F f2 { { 0 } }; // expected-error {{chosen constructor is explicit}} + F f3 { { { 0 } } }; // expected-error {{chosen constructor is explicit}} +} diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index 88571d6..9d89cce 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -144,7 +144,7 @@ namespace PR12119 { template<typename T> void g(std::initializer_list<std::initializer_list<T>>); void foo() { - f({0, {1}}); + f({0, {1}}); // expected-warning{{braces around scalar initializer}} g({{0, 1}, {2, 3}}); std::initializer_list<int> il = {1, 2}; g({il, {2, 3}}); @@ -208,3 +208,25 @@ namespace init_list_deduction_failure { void h() { g({f}); } // expected-error@-1 {{no matching function for call to 'g'}} } + +namespace deleted_copy { + struct X { + X(int i) {} + X(const X& x) = delete; // expected-note {{here}} + void operator=(const X& x) = delete; + }; + + std::initializer_list<X> x{1}; // expected-error {{invokes deleted constructor}} +} + +namespace RefVersusInitList { + struct S {}; + void f(const S &) = delete; + void f(std::initializer_list<S>); + void g(S s) { f({S()}); } +} + +namespace PR18013 { + int f(); + std::initializer_list<long (*)()> x = {f}; // expected-error {{cannot initialize an array element of type 'long (*const)()' with an lvalue of type 'int ()': different return type ('long' vs 'int')}} +} diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp index 0e4add8..db296bd 100644 --- a/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -122,3 +122,25 @@ namespace optional { o2 = optional<non_trivial>(); } } + +namespace pr16061 { + struct X { X(); }; + + template<typename T> struct Test1 { + union { + struct { + X x; + }; + }; + }; + + template<typename T> struct Test2 { + union { + struct { // expected-note {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field '' has a non-trivial default constructor}} + T x; + }; + }; + }; + + Test2<X> t2x; // expected-error {{call to implicitly-deleted default constructor of 'Test2<pr16061::X>'}} +} diff --git a/test/SemaCXX/cxx11-attr-print.cpp b/test/SemaCXX/cxx11-attr-print.cpp index 19de5b5..01325d3 100644 --- a/test/SemaCXX/cxx11-attr-print.cpp +++ b/test/SemaCXX/cxx11-attr-print.cpp @@ -52,7 +52,7 @@ inline void f6() __attribute__((gnu_inline)); inline void f7 [[gnu::gnu_inline]] (); // arguments printing -// CHECK: __attribute__((format("printf", 2, 3))); +// CHECK: __attribute__((format(printf, 2, 3))); void f8 (void *, const char *, ...) __attribute__ ((format (printf, 2, 3))); // CHECK: int m __attribute__((aligned(4 @@ -75,3 +75,6 @@ template <typename T> struct S { // CHECK: static int f() __attribute__((pure)) // CHECK: static int g() {{\[}}[gnu::pure]] template struct S<int>; + +// CHECK: using Small2 {{\[}}[gnu::mode(byte)]] = int; +using Small2 [[gnu::mode(byte)]] = int; diff --git a/test/SemaCXX/cxx11-crashes.cpp b/test/SemaCXX/cxx11-crashes.cpp index a4d4829..bd51af1 100644 --- a/test/SemaCXX/cxx11-crashes.cpp +++ b/test/SemaCXX/cxx11-crashes.cpp @@ -70,9 +70,7 @@ namespace b6981007 { for (auto x : s) { // We used to attempt to evaluate the initializer of this variable, // and crash because it has an undeduced type. - // FIXME: We should set the loop variable to be invalid if we can't build - // the loop, to suppress this follow-on error. - const int &n(x); // expected-error {{could not bind to an lvalue of type 'auto'}} + const int &n(x); } } } diff --git a/test/SemaCXX/cxx11-gnu-attrs.cpp b/test/SemaCXX/cxx11-gnu-attrs.cpp index def83a9..22d61a1 100644 --- a/test/SemaCXX/cxx11-gnu-attrs.cpp +++ b/test/SemaCXX/cxx11-gnu-attrs.cpp @@ -1,4 +1,4 @@ -// RUN: %clang -cc1 -triple x86_64-unknown-unknown -std=c++11 -verify %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -verify %s // Error cases. @@ -11,8 +11,9 @@ int *[[gnu::unused]] attr_on_ptr; // Valid cases. +void aliasb [[gnu::alias("_Z6alias1v")]] (); void alias1() {} -void alias2 [[gnu::alias("_Z6alias1v")]] (); +void aliasa [[gnu::alias("_Z6alias1v")]] (); [[gnu::aligned(8)]] int aligned; void aligned_fn [[gnu::aligned(32)]] (); diff --git a/test/SemaCXX/cxx11-thread-local-print.cpp b/test/SemaCXX/cxx11-thread-local-print.cpp index 9d9a82b..1adafbd 100644 --- a/test/SemaCXX/cxx11-thread-local-print.cpp +++ b/test/SemaCXX/cxx11-thread-local-print.cpp @@ -7,3 +7,9 @@ __thread int gnu_tl; _Thread_local int c11_tl; thread_local int cxx11_tl; +// CHECK: void foo() { +// CHECK: thread_local int cxx11_tl; +// CHECK: } +void foo() { + thread_local int cxx11_tl; +} diff --git a/test/SemaCXX/cxx1y-array-runtime-bound.cpp b/test/SemaCXX/cxx1y-array-runtime-bound.cpp deleted file mode 100644 index 1643adb..0000000 --- a/test/SemaCXX/cxx1y-array-runtime-bound.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// RUN: %clang_cc1 -std=c++1y %s -verify -triple=x86_64-linux-gnu -pedantic-errors - -// FIXME: many diagnostics here say 'variably modified type'. -// catch this case and say 'array of runtime bound' instead. - -namespace std { struct type_info; } - -struct S { - int arr[__SIZE_MAX__ / 32]; -}; -S s[32]; // expected-error {{array is too large}} - -int n; -int a[n]; // expected-error {{not allowed at file scope}} - -struct T { - int a[n]; // expected-error {{fields must have a constant size}} - static int b[n]; // expected-error {{not allowed at file scope}} -}; - -int g(int n, int a[n]); - -template<typename T> struct X {}; -template<int N, int[N]> struct Y {}; -template<int[n]> struct Z {}; // expected-error {{of variably modified type}} - -int f(int n) { - int arb[n]; // expected-note 3{{here}} - [arb] {} (); // expected-error {{cannot be captured}} - - // FIXME: an array of runtime bound can be captured by reference. - [&arb] { // expected-error {{cannot be captured}} - // Capturing the array implicitly captures the bound, if we need it - // in a range-based for loop. - for (auto &n : arb) { } // expected-error {{cannot be captured}} - } (); - - X<int[n]> x; // expected-error {{variably modified type}} - - int arb_neg[-1]; // expected-error {{negative size}} - int arb_of_array[n][2]; - int arr[3] = { 1, 2, 3, 4 }; // expected-error {{excess elements}} - char foo[4] = "fool"; // expected-error {{initializer-string for char array is too long}} - - static int not_auto1[n]; // expected-error {{can not have 'static'}} - extern int not_auto2[n]; // expected-error {{can not have 'extern'}} - // FIXME: say 'thread_local' not 'static'. - thread_local int not_auto1[n]; // expected-error {{can not have 'static'}} - - // FIXME: these should all be invalid. - auto &&ti1 = typeid(arb); - auto &&ti2 = typeid(int[n]); - auto &&so1 = sizeof(arb); - auto &&so2 = sizeof(int[n]); - auto *p = &arb; - decltype(arb) arb2; - int (*arbp)[n] = 0; - const int (&arbr)[n] = arbr; // expected-warning {{not yet bound}} - typedef int arbty[n]; - int array_of_arb[2][n]; - - struct Dyn { Dyn() {} Dyn(int) {} ~Dyn() {} }; - - // FIXME: these should be valid. - int arb_dynamic[n] = { 1, 2, 3, 4 }; // expected-error {{may not be initialized}} - Dyn dyn[n]; // expected-error {{non-POD}} - Dyn dyn_init[n] = { 1, 2, 3, 4 }; // expected-error {{non-POD}} -} diff --git a/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp b/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp new file mode 100644 index 0000000..58bbbb2 --- /dev/null +++ b/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp @@ -0,0 +1,177 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only %s +// RUN: %clang_cc1 -std=c++1y %s -verify -DCXX1Y + +// Explicit member declarations behave as in C++11. + +namespace n3323_example { + + template <class T> class zero_init { + public: + zero_init() : val(static_cast<T>(0)) {} + zero_init(T val) : val(val) {} + + operator T &() { return val; } //@13 + operator T() const { return val; } //@14 + + private: + T val; + }; + + void Delete() { + zero_init<int *> p; + p = new int(7); + delete p; //@23 + delete (p + 0); + delete + p; + } + + void Switch() { + zero_init<int> i; + i = 7; + switch (i) {} // @31 + switch (i + 0) {} + switch (+i) {} + } +} + +#ifdef CXX1Y +#else +//expected-error@23 {{ambiguous conversion of delete expression of type 'zero_init<int *>' to a pointer}} +//expected-note@13 {{conversion to pointer type 'int *'}} +//expected-note@14 {{conversion to pointer type 'int *'}} +//expected-error@31 {{multiple conversions from switch condition type 'zero_init<int>' to an integral or enumeration type}} +//expected-note@13 {{conversion to integral type 'int'}} +//expected-note@14 {{conversion to integral type 'int'}} +#endif + +namespace extended_examples { + + struct A0 { + operator int(); // matching and viable + }; + + struct A1 { + operator int() &&; // matching and not viable + }; + + struct A2 { + operator float(); // not matching + }; + + struct A3 { + template<typename T> operator T(); // not matching (ambiguous anyway) + }; + + struct A4 { + template<typename T> operator int(); // not matching (ambiguous anyway) + }; + + struct B1 { + operator int() &&; // @70 + operator int(); // @71 -- duplicate declaration with different qualifier is not allowed + }; + + struct B2 { + operator int() &&; // matching but not viable + operator float(); // not matching + }; + + void foo(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, B2 b2) { + switch (a0) {} + switch (a1) {} // @81 -- fails for different reasons + switch (a2) {} // @82 + switch (a3) {} // @83 + switch (a4) {} // @84 + switch (b2) {} // @85 -- fails for different reasons + } +} + +//expected-error@71 {{cannot overload a member function without a ref-qualifier with a member function with ref-qualifier '&&'}} +//expected-note@70 {{previous declaration is here}} +//expected-error@82 {{statement requires expression of integer type ('extended_examples::A2' invalid)}} +//expected-error@83 {{statement requires expression of integer type ('extended_examples::A3' invalid)}} +//expected-error@84 {{statement requires expression of integer type ('extended_examples::A4' invalid)}} + +#ifdef CXX1Y +//expected-error@81 {{statement requires expression of integer type ('extended_examples::A1' invalid)}} +//expected-error@85 {{statement requires expression of integer type ('extended_examples::B2' invalid)}} +#else +//expected-error@81 {{cannot initialize object parameter of type 'extended_examples::A1' with an expression of type 'extended_examples::A1'}} +//expected-error@85 {{cannot initialize object parameter of type 'extended_examples::B2' with an expression of type 'extended_examples::B2'}} +#endif + +namespace extended_examples_cxx1y { + + struct A1 { // leads to viable match in C++1y, and no viable match in C++11 + operator int() &&; // matching but not viable + template <typename T> operator T(); // In C++1y: matching and viable, since disambiguated by L.100 + }; + + struct A2 { // leads to ambiguity in C++1y, and no viable match in C++11 + operator int() &&; // matching but not viable + template <typename T> operator int(); // In C++1y: matching but ambiguous (disambiguated by L.105). + }; + + struct B1 { // leads to one viable match in both cases + operator int(); // matching and viable + template <typename T> operator T(); // In C++1y: matching and viable, since disambiguated by L.110 + }; + + struct B2 { // leads to one viable match in both cases + operator int(); // matching and viable + template <typename T> operator int(); // In C++1y: matching but ambiguous, since disambiguated by L.115 + }; + + struct C { // leads to no match in both cases + operator float(); // not matching + template <typename T> operator T(); // In C++1y: not matching, nor viable. + }; + + struct D { // leads to viable match in C++1y, and no viable match in C++11 + operator int() &&; // matching but not viable + operator float(); // not matching + template <typename T> operator T(); // In C++1y: matching and viable, since disambiguated by L.125 + }; + + + void foo(A1 a1, A2 a2, B1 b1, B2 b2, C c, D d) { + switch (a1) {} // @138 -- should presumably call templated conversion operator to convert to int. + switch (a2) {} // @139 + switch (b1) {} + switch (b2) {} + switch (c) {} // @142 + switch (d) {} // @143 + } +} + +//expected-error@142 {{statement requires expression of integer type ('extended_examples_cxx1y::C' invalid)}} + +#ifdef CXX1Y +//expected-error@139 {{statement requires expression of integer type ('extended_examples_cxx1y::A2' invalid)}} +#else +//expected-error@138 {{cannot initialize object parameter of type 'extended_examples_cxx1y::A1' with an expression of type 'extended_examples_cxx1y::A1'}} +//expected-error@139 {{cannot initialize object parameter of type 'extended_examples_cxx1y::A2' with an expression of type 'extended_examples_cxx1y::A2'}} +//expected-error@143 {{cannot initialize object parameter of type 'extended_examples_cxx1y::D' with an expression of type 'extended_examples_cxx1y::D'}} +#endif + +namespace extended_examples_array_bounds { + + typedef decltype(sizeof(int)) size_t; + + struct Foo { + operator size_t(); // @162 + operator unsigned short(); // @163 + }; + + void bar() { + Foo x; + int *p = new int[x]; // @168 + } +} + +#ifdef CXX1Y +#else +//expected-error@168 {{ambiguous conversion of array size expression of type 'extended_examples_array_bounds::Foo' to an integral or enumeration type}} +//expected-note@162 {{conversion to integral type 'size_t'}} +//expected-note@163 {{conversion to integral type 'unsigned short' declared here}} +#endif diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp index f0146f8..d3308b3 100644 --- a/test/SemaCXX/cxx1y-deduced-return-type.cpp +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING auto f(); // expected-note {{previous}} int f(); // expected-error {{differ only in their return type}} @@ -112,7 +113,8 @@ namespace Templates { int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}} template<typename T> auto fwd_decl() { return 0; } int f = fwd_decl<int>(); - template<typename T> auto fwd_decl(); + template <typename T> + auto fwd_decl(); // expected-note {{candidate template ignored: could not match 'auto ()' against 'int ()'}} int g = fwd_decl<char>(); auto (*p)() = f1; // expected-error {{incompatible initializer}} @@ -126,7 +128,8 @@ namespace Templates { extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}} int k2 = fwd_decl<char>(); - template<typename T> auto instantiate() { T::error; } // expected-error {{has no members}} + template <typename T> auto instantiate() { T::error; } // expected-error {{has no members}} \ + // expected-note {{candidate template ignored: could not match 'auto ()' against 'void ()'}} extern template auto instantiate<int>(); // ok int k = instantiate<int>(); // expected-note {{in instantiation of}} template<> auto instantiate<char>() {} // ok @@ -157,7 +160,7 @@ namespace Templates { double &mem_check4 = take_fn<double>(Outer<double>::arg_multi); namespace Deduce1 { - template<typename T> auto f() { return 0; } // expected-note {{candidate}} + template <typename T> auto f() { return 0; } // expected-note {{couldn't infer template argument 'T'}} template<typename T> void g(T(*)()); // expected-note 2{{candidate}} void h() { auto p = f<int>; @@ -170,7 +173,7 @@ namespace Templates { } namespace Deduce2 { - template<typename T> auto f(int) { return 0; } // expected-note {{candidate}} + template <typename T> auto f(int) { return 0; } // expected-note {{couldn't infer template argument 'T'}} template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}} void h() { auto p = f<int>; @@ -253,7 +256,7 @@ namespace DefaultedMethods { auto operator=(const A&) = default; // expected-error {{must return 'DefaultedMethods::A &'}} A &operator=(A&&); // expected-note {{previous}} }; - auto A::operator=(A&&) = default; // expected-error {{differs from the declaration in the return type}} + auto A::operator=(A&&) = default; // expected-error {{return type of out-of-line definition of 'DefaultedMethods::A::operator=' differs from that in the declaration}} } namespace Constexpr { @@ -295,7 +298,12 @@ namespace NoReturn { auto f() {} void (*p)() = &f; + auto f(); // ok + auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} + + auto h() = delete; // expected-note {{explicitly deleted}} + auto x = h(); // expected-error {{call to deleted}} } namespace UseBeforeComplete { @@ -317,7 +325,8 @@ namespace Redecl { int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}} decltype(auto) f(); // expected-error {{cannot be overloaded}} - template<typename T> auto g(T t) { return t; } // expected-note {{candidate}} + template <typename T> auto g(T t) { return t; } // expected-note {{candidate}} \ + // expected-note {{candidate function [with T = int]}} template auto g(int); template char g(char); // expected-error {{does not refer to a function}} template<> auto g(double); @@ -334,5 +343,136 @@ namespace ExplicitInstantiationDecl { extern template auto f(int); int (*p)(int) = f; } +namespace MemberTemplatesWithDeduction { + struct M { + template<class T> auto foo(T t) { return t; } + template<class T> auto operator()(T t) const { return t; } + template<class T> static __attribute__((unused)) int static_foo(T) { + return 5; + } + template<class T> operator T() { return T{}; } + operator auto() { return &static_foo<int>; } + }; + struct N : M { + using M::foo; + using M::operator(); + using M::static_foo; + using M::operator auto; + }; + + template <class T> int test() { + int i = T{}.foo(3); + T m = T{}.foo(M{}); + int j = T{}(3); + M m2 = M{}(M{}); + int k = T{}.static_foo(4); + int l = T::static_foo(5); + int l2 = T{}; + struct X { }; + X x = T{}; + return 0; + } + int Minst = test<M>(); + int Ninst = test<N>(); + +} +} + +namespace CurrentInstantiation { + // PR16875 + template<typename T> struct S { + auto f() { return T(); } + int g() { return f(); } + auto h(bool b) { + if (b) + return T(); + return h(true); + } + }; + int k1 = S<int>().g(); + int k2 = S<int>().h(false); + + template<typename T> struct U { + #ifndef DELAYED_TEMPLATE_PARSING + auto f(); // expected-note {{here}} + int g() { return f(); } // expected-error {{cannot be used before it is defined}} + #else + auto f(); + int g() { return f(); } + #endif + }; + #ifndef DELAYED_TEMPLATE_PARSING + template int U<int>::g(); // expected-note {{in instantiation of}} + #else + template int U<int>::g(); + #endif + template<typename T> auto U<T>::f() { return T(); } + template int U<short>::g(); // ok +} + +namespace WithDefaultArgs { + template<typename U> struct A { + template<typename T = U> friend auto f(A) { return []{}; } + }; + template<typename T> void f(); + using T = decltype(f(A<int>())); + using T = decltype(f<int>(A<int>())); +} + +namespace MultilevelDeduction { + +auto F() -> auto* { return (int*)0; } + +auto (*G())() -> int* { return F; } + +auto run = G(); + +namespace Templated { +template<class T> +auto F(T t) -> auto* { return (T*)0; } + +template<class T> +auto (*G(T t))(T) -> T* { return &F<T>; } + + +template<class T> +auto (*G2(T t))(T) -> auto* { return &F<T>; } + +auto run_int = G(1); +auto run_char = G2('a'); + +} +} + +namespace rnk { +extern "C" int puts(const char *s); +template <typename T> +auto foo(T x) -> decltype(x) { +#ifdef DELAYED_TEMPLATE_PARSING + ::rnk::bar(); +#endif + return x; +} +void bar() { puts("bar"); } +int main() { return foo(0); } } + +namespace OverloadedOperators { + template<typename T> struct A { + auto operator()() { return T{}; } + auto operator[](int) { return T{}; } + auto operator+(int) { return T{}; } + auto operator+() { return T{}; } + friend auto operator-(A) { return T{}; } + friend auto operator-(A, A) { return T{}; } + }; + void f(A<int> a) { + int b = a(); + int c = a[0]; + int d = a + 0; + int e = +a; + int f = -a; + int g = a - a; + } +} diff --git a/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp b/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp new file mode 100644 index 0000000..8bd4f42 --- /dev/null +++ b/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp @@ -0,0 +1,1363 @@ +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s +// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING +// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS +// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING + +constexpr int ODRUSE_SZ = sizeof(char); + +template<class T, int N> +void f(T, const int (&)[N]) { } + +template<class T> +void f(const T&, const int (&)[ODRUSE_SZ]) { } + +#define DEFINE_SELECTOR(x) \ + int selector_ ## x[sizeof(x) == ODRUSE_SZ ? ODRUSE_SZ : ODRUSE_SZ + 5] + +#define F_CALL(x, a) f(x, selector_ ## a) + +// This is a risky assumption, because if an empty class gets captured by value +// the lambda's size will still be '1' +#define ASSERT_NO_CAPTURES(L) static_assert(sizeof(L) == 1, "size of closure with no captures must be 1") +#define ASSERT_CLOSURE_SIZE_EXACT(L, N) static_assert(sizeof(L) == (N), "size of closure must be " #N) +#define ASSERT_CLOSURE_SIZE(L, N) static_assert(sizeof(L) >= (N), "size of closure must be >=" #N) + + +namespace sample { + struct X { + int i; + X(int i) : i(i) { } + }; +} + +namespace test_transformations_in_templates { +template<class T> void foo(T t) { + auto L = [](auto a) { return a; }; +} +template<class T> void foo2(T t) { + auto L = [](auto a) -> void { + auto M = [](char b) -> void { + auto N = [](auto c) -> void { + int selector[sizeof(c) == 1 ? + (sizeof(b) == 1 ? 1 : 2) + : 2 + ]{}; + }; + N('a'); + }; + }; + L(3.14); +} + +void doit() { + foo(3); + foo('a'); + foo2('A'); +} +} + +namespace test_return_type_deduction { + +void doit() { + + auto L = [](auto a, auto b) { + if ( a > b ) return a; + return b; + }; + L(2, 4); + { + auto L2 = [](auto a, int i) { + return a + i; + }; + L2(3.14, 2); + } + { + int a; //expected-note{{declared here}} + auto B = []() { return ^{ return a; }; }; //expected-error{{cannot be implicitly capture}}\ + //expected-note{{begins here}} + //[](){ return ({int b = 5; return 'c'; 'x';}); }; + + //auto X = ^{ return a; }; + + //auto Y = []() -> auto { return 3; return 'c'; }; + + } +} +} + + +namespace test_no_capture{ +void doit() { + const int x = 10; //expected-note{{declared here}} + { + // should not capture 'x' - variable undergoes lvalue-to-rvalue + auto L = [=](auto a) { + int y = x; + return a + y; + }; + ASSERT_NO_CAPTURES(L); + } + { + // should not capture 'x' - even though certain instantiations require + auto L = [](auto a) { //expected-note{{begins here}} + DEFINE_SELECTOR(a); + F_CALL(x, a); //expected-error{{'x' cannot be implicitly captured}} + }; + ASSERT_NO_CAPTURES(L); + L('s'); //expected-note{{in instantiation of}} + } + { + // Does not capture because no default capture in inner most lambda 'b' + auto L = [=](auto a) { + return [=](int p) { + return [](auto b) { + DEFINE_SELECTOR(a); + F_CALL(x, a); + return 0; + }; + }; + }; + ASSERT_NO_CAPTURES(L); + } +} // doit +} // namespace + +namespace test_capture_of_potentially_evaluated_expression { +void doit() { + const int x = 5; + { + auto L = [=](auto a) { + DEFINE_SELECTOR(a); + F_CALL(x, a); + }; + static_assert(sizeof(L) == 4, "Must be captured"); + } + { + int j = 0; //expected-note{{declared}} + auto L = [](auto a) { //expected-note{{begins here}} + return j + 1; //expected-error{{cannot be implicitly captured}} + }; + } + { + const int x = 10; + auto L = [](auto a) { + //const int y = 20; + return [](int p) { + return [](auto b) { + DEFINE_SELECTOR(a); + F_CALL(x, a); + return 0; + }; + }; + }; + auto M = L(3); + auto N = M(5); + + } + + { // if the nested capture does not implicitly or explicitly allow any captures + // nothing should capture - and instantiations will create errors if needed. + const int x = 0; + auto L = [=](auto a) { // <-- #A + const int y = 0; + return [](auto b) { // <-- #B + int c[sizeof(b)]; + f(x, c); + f(y, c); + int i = x; + }; + }; + ASSERT_NO_CAPTURES(L); + auto M_int = L(2); + ASSERT_NO_CAPTURES(M_int); + } + { // Permutations of this example must be thoroughly tested! + const int x = 0; + sample::X cx{5}; + auto L = [=](auto a) { + const int z = 3; + return [&,a](auto b) { + const int y = 5; + return [=](auto c) { + int d[sizeof(a) == sizeof(c) || sizeof(c) == sizeof(b) ? 2 : 1]; + f(x, d); + f(y, d); + f(z, d); + decltype(a) A = a; + decltype(b) B = b; + const int &i = cx.i; + }; + }; + }; + auto M = L(3)(3.5); + M(3.14); + } +} +namespace Test_no_capture_of_clearly_no_odr_use { +auto foo() { + const int x = 10; + auto L = [=](auto a) { + return [=](auto b) { + return [=](auto c) { + int A = x; + return A; + }; + }; + }; + auto M = L(1); + auto N = M(2.14); + ASSERT_NO_CAPTURES(L); + ASSERT_NO_CAPTURES(N); + + return 0; +} +} + +namespace Test_capture_of_odr_use_var { +auto foo() { + const int x = 10; + auto L = [=](auto a) { + return [=](auto b) { + return [=](auto c) { + int A = x; + const int &i = x; + decltype(a) A2 = a; + return A; + }; + }; + }; + auto M_int = L(1); + auto N_int_int = M_int(2); + ASSERT_CLOSURE_SIZE_EXACT(L, sizeof(x)); + // M_int captures both a & x + ASSERT_CLOSURE_SIZE_EXACT(M_int, sizeof(x) + sizeof(int)); + // N_int_int captures both a & x + ASSERT_CLOSURE_SIZE_EXACT(N_int_int, sizeof(x) + sizeof(int)); + auto M_double = L(3.14); + ASSERT_CLOSURE_SIZE(M_double, sizeof(x) + sizeof(double)); + + return 0; +} +auto run = foo(); +} + +} +namespace more_nested_captures_1 { +template<class T> struct Y { + static void f(int, double, ...) { } + template<class R> + static void f(const int&, R, ...) { } + template<class R> + void foo(R t) { + const int x = 10; //expected-note{{declared here}} + auto L = [](auto a) { + return [=](auto b) { + return [=](auto c) { + f(x, c, b, a); //expected-error{{reference to local variable 'x'}} + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3.14); + N(5); //expected-note{{in instantiation of}} + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} +} + + +namespace more_nested_captures_1_1 { +template<class T> struct Y { + static void f(int, double, ...) { } + template<class R> + static void f(const int&, R, ...) { } + template<class R> + void foo(R t) { + const int x = 10; //expected-note{{declared here}} + auto L = [](auto a) { + return [=](char b) { + return [=](auto c) { + f(x, c, b, a); //expected-error{{reference to local variable 'x'}} + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3.14); + N(5); //expected-note{{in instantiation of}} + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} +} +namespace more_nested_captures_1_2 { +template<class T> struct Y { + static void f(int, double, ...) { } + template<class R> + static void f(const int&, R, ...) { } + template<class R> + void foo(R t) { + const int x = 10; + auto L = [=](auto a) { + return [=](char b) { + return [=](auto c) { + f(x, c, b, a); + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3.14); + N(5); + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); +} + +namespace more_nested_captures_1_3 { +template<class T> struct Y { + static void f(int, double, ...) { } + template<class R> + static void f(const int&, R, ...) { } + template<class R> + void foo(R t) { + const int x = 10; //expected-note{{declared here}} + auto L = [=](auto a) { + return [](auto b) { + const int y = 0; + return [=](auto c) { + f(x, c, b); //expected-error{{reference to local variable 'x'}} + f(y, b, c); + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3.14); + N(5); //expected-note{{in instantiation of}} + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} +} + + +namespace more_nested_captures_1_4 { +template<class T> struct Y { + static void f(int, double, ...) { } + template<class R> + static void f(const int&, R, ...) { } + template<class R> + void foo(R t) { + const int x = 10; //expected-note{{declared here}} + auto L = [=](auto a) { + T t2{t}; + return [](auto b) { + const int y = 0; //expected-note{{declared here}} + return [](auto c) { //expected-note 2{{lambda expression begins here}} + f(x, c); //expected-error{{variable 'x'}} + f(y, c); //expected-error{{variable 'y'}} + return 0; + }; + }; + }; + auto M = L(t); + auto N_char = M('b'); + N_char(3.14); + auto N_double = M(3.14); + N_double(3.14); + N_char(3); //expected-note{{in instantiation of}} + } +}; +Y<int> yi; +int run = (yi.foo('a'), 0); //expected-note{{in instantiation of}} +} + + +namespace more_nested_captures_2 { +template<class T> struct Y { + static void f(int, double) { } + template<class R> + static void f(const int&, R) { } + template<class R> + void foo(R t) { + const int x = 10; + auto L = [=](auto a) { + return [=](auto b) { + return [=](auto c) { + f(x, c); + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3); + N(3.14); + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); + +} + +namespace more_nested_captures_3 { +template<class T> struct Y { + static void f(int, double) { } + template<class R> + static void f(const int&, R) { } + template<class R> + void foo(R t) { + const int x = 10; //expected-note{{declared here}} + auto L = [](auto a) { + return [=](auto b) { + return [=](auto c) { + f(x, c); //expected-error{{reference to local variable 'x'}} + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3); //expected-note{{in instantiation of}} + N(3.14); + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} + +} + +namespace more_nested_captures_4 { +template<class T> struct Y { + static void f(int, double) { } + template<class R> + static void f(const int&, R) { } + template<class R> + void foo(R t) { + const int x = 10; //expected-note{{'x' declared here}} + auto L = [](auto a) { + return [=](char b) { + return [=](auto c) { + f(x, c); //expected-error{{reference to local variable 'x'}} + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3); //expected-note{{in instantiation of}} + N(3.14); + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} + +} + +namespace more_nested_captures_5 { +template<class T> struct Y { + static void f(int, double) { } + template<class R> + static void f(const int&, R) { } + template<class R> + void foo(R t) { + const int x = 10; + auto L = [=](auto a) { + return [=](char b) { + return [=](auto c) { + f(x, c); + return 0; + }; + }; + }; + auto M = L(t); + auto N = M('b'); + N(3); + N(3.14); + } +}; +Y<int> yi; +int run = (yi.foo(3.14), 0); + +} + +namespace lambdas_in_NSDMIs { +template<class T> + struct L { + T t{}; + T t2 = ([](auto a) { return [](auto b) { return b; };})(t)(t); + T t3 = ([](auto a) { return a; })(t); + }; + L<int> l; + int run = l.t2; +} +namespace test_nested_decltypes_in_trailing_return_types { +int foo() { + auto L = [](auto a) { + return [](auto b, decltype(a) b2) -> decltype(a) { + return decltype(a){}; + }; + }; + auto M = L(3.14); + M('a', 6.26); + return 0; +} +} + +namespace more_this_capture_1 { +struct X { + void f(int) { } + static void f(double) { } + void foo() { + { + auto L = [=](auto a) { + f(a); + }; + L(3); + L(3.13); + } + { + auto L = [](auto a) { + f(a); //expected-error{{this}} + }; + L(3.13); + L(2); //expected-note{{in instantiation}} + } + } + + int g() { + auto L = [=](auto a) { + return [](int i) { + return [=](auto b) { + f(b); + int x = i; + }; + }; + }; + auto M = L(0.0); + auto N = M(3); + N(5.32); // OK + return 0; + } +}; +int run = X{}.g(); +} +namespace more_this_capture_1_1 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [](int i) { + return [=](auto b) { + f(decltype(a){}); //expected-error{{this}} + int x = i; + }; + }; + }; + auto M = L(0.0); + auto N = M(3); + N(5.32); // OK + L(3); // expected-note{{instantiation}} + return 0; + } +}; +int run = X{}.g(); +} + +namespace more_this_capture_1_1_1 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [](auto b) { + return [=](int i) { + f(b); + f(decltype(a){}); //expected-error{{this}} + }; + }; + }; + auto M = L(0.0); // OK + auto N = M(3.3); //OK + auto M_int = L(0); //expected-note{{instantiation}} + return 0; + } +}; +int run = X{}.g(); +} + + +namespace more_this_capture_1_1_1_1 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [](auto b) { + return [=](int i) { + f(b); //expected-error{{this}} + f(decltype(a){}); + }; + }; + }; + auto M_double = L(0.0); // OK + auto N = M_double(3); //expected-note{{instantiation}} + + return 0; + } +}; +int run = X{}.g(); +} + +namespace more_this_capture_2 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [](int i) { + return [=](auto b) { + f(b); //expected-error{{'this' cannot}} + int x = i; + }; + }; + }; + auto M = L(0.0); + auto N = M(3); + N(5); // NOT OK expected-note{{in instantiation of}} + return 0; + } +}; +int run = X{}.g(); +} +namespace diagnose_errors_early_in_generic_lambdas { + +int foo() +{ + + { // This variable is used and must be caught early, do not need instantiation + const int x = 0; //expected-note{{declared}} + auto L = [](auto a) { //expected-note{{begins}} + const int &r = x; //expected-error{{variable}} + }; + } + { // This variable is not used + const int x = 0; + auto L = [](auto a) { + int i = x; + }; + } + { + + const int x = 0; //expected-note{{declared}} + auto L = [=](auto a) { // <-- #A + const int y = 0; + return [](auto b) { //expected-note{{begins}} + int c[sizeof(b)]; + f(x, c); + f(y, c); + int i = x; + // This use will always be an error regardless of instantatiation + // so diagnose this early. + const int &r = x; //expected-error{{variable}} + }; + }; + + } + return 0; +} + +int run = foo(); +} + +namespace generic_nongenerics_interleaved_1 { +int foo() { + { + auto L = [](int a) { + int y = 10; + return [=](auto b) { + return a + y; + }; + }; + auto M = L(3); + M(5); + } + { + int x; + auto L = [](int a) { + int y = 10; + return [=](auto b) { + return a + y; + }; + }; + auto M = L(3); + M(5); + } + { + // FIXME: why are there 2 error messages here? + int x; + auto L = [](auto a) { //expected-note {{declared here}} + int y = 10; //expected-note {{declared here}} + return [](int b) { //expected-note 2{{expression begins here}} + return [=] (auto c) { + return a + y; //expected-error 2{{cannot be implicitly captured}} + }; + }; + }; + } + { + int x; + auto L = [](auto a) { + int y = 10; + return [=](int b) { + return [=] (auto c) { + return a + y; + }; + }; + }; + } + return 1; +} + +int run = foo(); +} +namespace dont_capture_refs_if_initialized_with_constant_expressions { + +auto foo(int i) { + // This is surprisingly not odr-used within the lambda! + static int j; + j = i; + int &ref_j = j; + return [](auto a) { return ref_j; }; // ok +} + +template<class T> +auto foo2(T t) { + // This is surprisingly not odr-used within the lambda! + static T j; + j = t; + T &ref_j = j; + return [](auto a) { return ref_j; }; // ok +} + +int do_test() { + auto L = foo(3); + auto L_int = L(3); + auto L_char = L('a'); + auto L1 = foo2(3.14); + auto L1_int = L1(3); + auto L1_char = L1('a'); + return 0; +} + +} // dont_capture_refs_if_initialized_with_constant_expressions + +namespace test_conversion_to_fptr { + +template<class T> struct X { + + T (*fp)(T) = [](auto a) { return a; }; + +}; + +X<int> xi; + +template<class T> +void fooT(T t, T (*fp)(T) = [](auto a) { return a; }) { + fp(t); +} + +int test() { +{ + auto L = [](auto a) { return a; }; + int (*fp)(int) = L; + fp(5); + L(3); + char (*fc)(char) = L; + fc('b'); + L('c'); + double (*fd)(double) = L; + fd(3.14); + fd(6.26); + L(4.25); +} +{ + auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}} + int (*fp)(int) = L; + char (*fc)(char) = L; //expected-error{{no viable conversion}} + double (*fd)(double) = L; //expected-error{{no viable conversion}} +} +{ + int x = 5; + auto L = [=](auto b, char c = 'x') { + int i = x; + return [](auto a) ->decltype(a) { return a; }; + }; + int (*fp)(int) = L(8); + fp(5); + L(3); + char (*fc)(char) = L('a'); + fc('b'); + L('c'); + double (*fd)(double) = L(3.14); + fd(3.14); + fd(6.26); + +} +{ + auto L = [=](auto b) { + return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; + }; + int* (*fp)(int) = L(8); + fp(5); + L(3); + char* (*fc)(char) = L('a'); + fc('b'); + L('c'); + double* (*fd)(double) = L(3.14); + fd(3.14); + fd(6.26); +} +{ + auto L = [=](auto b) { + return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; //expected-note{{candidate template ignored}} + }; + char* (*fp)(int) = L('8'); + fp(5); + char* (*fc)(char) = L('a'); + fc('b'); + double* (*fi)(int) = L(3.14); + fi(5); + int* (*fi2)(int) = L(3.14); //expected-error{{no viable conversion}} +} + +{ + auto L = [=](auto b) { + return [](auto a) { + return [=](auto c) { + return [](auto d) ->decltype(a + b + c + d) { return d; }; + }; + }; + }; + int (*fp)(int) = L('8')(3)(short{}); + double (*fs)(char) = L(3.14)(short{})('4'); +} + + fooT(3); + fooT('a'); + fooT(3.14); + fooT("abcdefg"); + return 0; +} +int run2 = test(); + +} + + +namespace this_capture { +void f(char, int) { } +template<class T> +void f(T, const int&) { } + +struct X { + int x = 0; + void foo() { + auto L = [=](auto a) { + return [=](auto b) { + //f(a, x++); + x++; + }; + }; + L('a')(5); + L('b')(4); + L(3.14)('3'); + + } + +}; + +int run = (X{}.foo(), 0); + +namespace this_capture_unresolvable { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto lam = [=](auto a) { f(a); }; // captures 'this' + lam(0); // ok. + lam(0.0); // ok. + return 0; + } + int g2() { + auto lam = [](auto a) { f(a); }; // expected-error{{'this'}} + lam(0); // expected-note{{in instantiation of}} + lam(0.0); // ok. + return 0; + } + double (*fd)(double) = [](auto a) { f(a); return a; }; + +}; + +int run = X{}.g(); + +} + +namespace check_nsdmi_and_this_capture_of_member_functions { + +struct FunctorDouble { + template<class T> FunctorDouble(T t) { t(2.14); }; +}; +struct FunctorInt { + template<class T> FunctorInt(T t) { t(2); }; //expected-note{{in instantiation of}} +}; + +template<class T> struct YUnresolvable { + void f(int) { } + static void f(double) { } + + T t = [](auto a) { f(a); return a; }; + T t2 = [=](auto b) { f(b); return b; }; +}; + +template<class T> struct YUnresolvable2 { + void f(int) { } + static void f(double) { } + + T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} \ + //expected-note{{in instantiation of}} + T t2 = [=](auto b) { f(b); return b; }; +}; + + +YUnresolvable<FunctorDouble> yud; +// This will cause an error since it call's with an int and calls a member function. +YUnresolvable2<FunctorInt> yui; + + +template<class T> struct YOnlyStatic { + static void f(double) { } + + T t = [](auto a) { f(a); return a; }; +}; +YOnlyStatic<FunctorDouble> yos; +template<class T> struct YOnlyNonStatic { + void f(int) { } + + T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} +}; + + +} + + +namespace check_nsdmi_and_this_capture_of_data_members { + +struct FunctorDouble { + template<class T> FunctorDouble(T t) { t(2.14); }; +}; +struct FunctorInt { + template<class T> FunctorInt(T t) { t(2); }; +}; + +template<class T> struct YThisCapture { + const int x = 10; + static double d; + T t = [](auto a) { return x; }; //expected-error{{'this'}} + T t2 = [](auto b) { return d; }; + T t3 = [this](auto a) { + return [=](auto b) { + return x; + }; + }; + T t4 = [=](auto a) { + return [=](auto b) { + return x; + }; + }; + T t5 = [](auto a) { + return [=](auto b) { + return x; //expected-error{{'this'}} + }; + }; +}; + +template<class T> double YThisCapture<T>::d = 3.14; + + +} + + +#ifdef DELAYED_TEMPLATE_PARSING +template<class T> void foo_no_error(T t) { + auto L = []() + { return t; }; +} +template<class T> void foo(T t) { //expected-note 2{{declared here}} + auto L = []() //expected-note 2{{begins here}} + { return t; }; //expected-error 2{{cannot be implicitly captured}} +} +template void foo(int); //expected-note{{in instantiation of}} + +#else + +template<class T> void foo(T t) { //expected-note{{declared here}} + auto L = []() //expected-note{{begins here}} + { return t; }; //expected-error{{cannot be implicitly captured}} +} + +#endif +} + +namespace no_this_capture_for_static { + +struct X { + static void f(double) { } + + int g() { + auto lam = [=](auto a) { f(a); }; + lam(0); // ok. + ASSERT_NO_CAPTURES(lam); + return 0; + } +}; + +int run = X{}.g(); +} + +namespace this_capture_for_non_static { + +struct X { + void f(double) { } + + int g() { + auto L = [=](auto a) { f(a); }; + L(0); + auto L2 = [](auto a) { f(a); }; //expected-error {{cannot be implicitly captured}} + return 0; + } +}; + +int run = X{}.g(); +} + +namespace this_captures_with_num_args_disambiguation { + +struct X { + void f(int) { } + static void f(double, int i) { } + int g() { + auto lam = [](auto a) { f(a, a); }; + lam(0); + return 0; + } +}; + +int run = X{}.g(); +} +namespace enclosing_function_is_template_this_capture { +// Only error if the instantiation tries to use the member function. +struct X { + void f(int) { } + static void f(double) { } + template<class T> + int g(T t) { + auto L = [](auto a) { f(a); }; //expected-error{{'this'}} + L(t); // expected-note{{in instantiation of}} + return 0; + } +}; + +int run = X{}.g(0.0); // OK. +int run2 = X{}.g(0); // expected-note{{in instantiation of}} + + +} + +namespace enclosing_function_is_template_this_capture_2 { +// This should error, even if not instantiated, since +// this would need to be captured. +struct X { + void f(int) { } + template<class T> + int g(T t) { + auto L = [](auto a) { f(a); }; //expected-error{{'this'}} + L(t); + return 0; + } +}; + +} + + +namespace enclosing_function_is_template_this_capture_3 { +// This should not error, this does not need to be captured. +struct X { + static void f(int) { } + template<class T> + int g(T t) { + auto L = [](auto a) { f(a); }; + L(t); + return 0; + } +}; + +int run = X{}.g(0.0); // OK. +int run2 = X{}.g(0); // OK. + +} + +namespace nested_this_capture_1 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [this]() { + return [=](auto b) { + f(b); + }; + }; + }; + auto M = L(0); + auto N = M(); + N(5); + return 0; + } +}; + +int run = X{}.g(); + +} + + +namespace nested_this_capture_2 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [&]() { + return [=](auto b) { + f(b); + }; + }; + }; + auto M = L(0); + auto N = M(); + N(5); + N(3.14); + return 0; + } +}; + +int run = X{}.g(); + +} + +namespace nested_this_capture_3_1 { +struct X { + template<class T> + void f(int, T t) { } + template<class T> + static void f(double, T t) { } + + int g() { + auto L = [=](auto a) { + return [&](auto c) { + return [=](auto b) { + f(b, c); + }; + }; + }; + auto M = L(0); + auto N = M('a'); + N(5); + N(3.14); + return 0; + } +}; + +int run = X{}.g(); + +} + + +namespace nested_this_capture_3_2 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [=](auto a) { + return [](int i) { + return [=](auto b) { + f(b); //expected-error {{'this' cannot}} + int x = i; + }; + }; + }; + auto M = L(0.0); + auto N = M(3); + N(5); //expected-note {{in instantiation of}} + N(3.14); // OK. + return 0; + } +}; + +int run = X{}.g(); + +} + +namespace nested_this_capture_4 { +struct X { + void f(int) { } + static void f(double) { } + + int g() { + auto L = [](auto a) { + return [=](auto i) { + return [=](auto b) { + f(b); //expected-error {{'this' cannot}} + int x = i; + }; + }; + }; + auto M = L(0.0); + auto N = M(3); + N(5); //expected-note {{in instantiation of}} + N(3.14); // OK. + return 0; + } +}; + +int run = X{}.g(); + +} +namespace capture_enclosing_function_parameters { + + +inline auto foo(int x) { + int i = 10; + auto lambda = [=](auto z) { return x + z; }; + return lambda; +} + +int foo2() { + auto L = foo(3); + L(4); + L('a'); + L(3.14); + return 0; +} + +inline auto foo3(int x) { + int local = 1; + auto L = [=](auto a) { + int i = a[local]; + return [=](auto b) mutable { + auto n = b; + return [&, n](auto c) mutable { + ++local; + return ++x; + }; + }; + }; + auto M = L("foo-abc"); + auto N = M("foo-def"); + auto O = N("foo-ghi"); + + return L; +} + +int main() { + auto L3 = foo3(3); + auto M3 = L3("L3-1"); + auto N3 = M3("M3-1"); + auto O3 = N3("N3-1"); + N3("N3-2"); + M3("M3-2"); + M3("M3-3"); + L3("L3-2"); +} +} // end ns + +namespace capture_arrays { + +inline int sum_array(int n) { + int array2[5] = { 1, 2, 3, 4, 5}; + + auto L = [=](auto N) -> int { + int sum = 0; + int array[5] = { 1, 2, 3, 4, 5 }; + sum += array2[sum]; + sum += array2[N]; + return 0; + }; + L(2); + return L(n); +} +} + +namespace capture_non_odr_used_variable_because_named_in_instantiation_dependent_expressions { + +// even though 'x' is not odr-used, it should be captured. + +int test() { + const int x = 10; + auto L = [=](auto a) { + (void) +x + a; + }; + ASSERT_CLOSURE_SIZE_EXACT(L, sizeof(x)); +} + +} //end ns +#ifdef MS_EXTENSIONS +namespace explicit_spec { +template<class R> struct X { + template<class T> int foo(T t) { + auto L = [](auto a) { return a; }; + L(&t); + return 0; + } + + template<> int foo<char>(char c) { //expected-warning{{explicit specialization}} + const int x = 10; + auto LC = [](auto a) { return a; }; + R r; + LC(&r); + auto L = [=](auto a) { + return [=](auto b) { + int d[sizeof(a)]; + f(x, d); + }; + }; + auto M = L(1); + + ASSERT_NO_CAPTURES(M); + return 0; + } + +}; + +int run_char = X<int>{}.foo('a'); +int run_int = X<double>{}.foo(4); +} + +#endif // MS_EXTENSIONS + diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp new file mode 100644 index 0000000..20e06f4 --- /dev/null +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -0,0 +1,908 @@ +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING + +namespace explicit_call { +int test() { + auto L = [](auto a) { return a; }; + L.operator()(3); + L.operator()<char>(3.14); //expected-warning{{implicit conversion}} + return 0; +} +} //end ns + +namespace test_conversion_to_fptr_2 { + +template<class T> struct X { + + T (*fp)(T) = [](auto a) { return a; }; + +}; + +X<int> xi; + +template<class T> +void fooT(T t, T (*fp)(T) = [](auto a) { return a; }) { + fp(t); +} + +int test() { +{ + auto L = [](auto a) { return a; }; + int (*fp)(int) = L; + fp(5); + L(3); + char (*fc)(char) = L; + fc('b'); + L('c'); + double (*fd)(double) = L; + fd(3.14); + fd(6.26); + L(4.25); +} +{ + auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}} + int (*fp)(int) = L; + char (*fc)(char) = L; //expected-error{{no viable conversion}} + double (*fd)(double) = L; //expected-error{{no viable conversion}} +} +{ + int x = 5; + auto L = [=](auto b, char c = 'x') { + int i = x; + return [](auto a) ->decltype(a) { return a; }; + }; + int (*fp)(int) = L(8); + fp(5); + L(3); + char (*fc)(char) = L('a'); + fc('b'); + L('c'); + double (*fd)(double) = L(3.14); + fd(3.14); + fd(6.26); + +} +{ + auto L = [=](auto b) { + return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; + }; + int* (*fp)(int) = L(8); + fp(5); + L(3); + char* (*fc)(char) = L('a'); + fc('b'); + L('c'); + double* (*fd)(double) = L(3.14); + fd(3.14); + fd(6.26); +} +{ + auto L = [=](auto b) { + return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; //expected-note{{candidate template ignored}} + }; + char* (*fp)(int) = L('8'); + fp(5); + char* (*fc)(char) = L('a'); + fc('b'); + double* (*fi)(int) = L(3.14); + fi(5); + int* (*fi2)(int) = L(3.14); //expected-error{{no viable conversion}} +} + +{ + auto L = [=](auto b) { + return [](auto a) { + return [=](auto c) { + return [](auto d) ->decltype(a + b + c + d) { return d; }; + }; + }; + }; + int (*fp)(int) = L('8')(3)(short{}); + double (*fs)(char) = L(3.14)(short{})('4'); +} + + fooT(3); + fooT('a'); + fooT(3.14); + fooT("abcdefg"); + return 0; +} +int run2 = test(); + +} + + +namespace test_conversion_to_fptr { + +void f1(int (*)(int)) { } +void f2(char (*)(int)) { } // expected-note{{candidate}} +void g(int (*)(int)) { } // #1 expected-note{{candidate}} +void g(char (*)(char)) { } // #2 expected-note{{candidate}} +void h(int (*)(int)) { } // #3 +void h(char (*)(int)) { } // #4 + +int test() { +{ + auto glambda = [](auto a) { return a; }; + glambda(1); + f1(glambda); // OK + f2(glambda); // expected-error{{no matching function}} + g(glambda); // expected-error{{call to 'g' is ambiguous}} + h(glambda); // OK: calls #3 since it is convertible from ID + + int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK + +} +{ + + auto L = [](auto a) { return a; }; + int (*fp)(int) = L; + fp(5); + L(3); + char (*fc)(char) = L; + fc('b'); + L('c'); + double (*fd)(double) = L; + fd(3.14); + fd(6.26); + L(4.25); +} +{ + auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}} + int (*fp)(int) = L; + char (*fc)(char) = L; //expected-error{{no viable conversion}} + double (*fd)(double) = L; //expected-error{{no viable conversion}} +} +{ + int* (*fp)(int*) = [](auto *a) -> auto* { return a; }; + fp(0); +} +} + +namespace more_converion_to_ptr_to_function_tests { + + +int test() { + { + int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK + int (*fp2)(int) = [](auto b) -> int { return b; }; + int (*fp3)(char) = [](auto c) -> int { return c; }; + char (*fp4)(int) = [](auto d) { return d; }; //expected-error{{no viable conversion}}\ + //expected-note{{candidate template ignored}} + char (*fp5)(char) = [](auto e) -> int { return e; }; //expected-error{{no viable conversion}}\ + //expected-note{{candidate template ignored}} + + fp2(3); + fp3('\n'); + fp3('a'); + return 0; + } +} // end test() + +template<class ... Ts> void vfun(Ts ... ) { } + +int variadic_test() { + + int (*fp)(int, char, double) = [](auto ... a) -> int { vfun(a...); return 4; }; + fp(3, '4', 3.14); + + int (*fp2)(int, char, double) = [](auto ... a) { vfun(a...); return 4; }; + fp(3, '4', 3.14); + return 2; +} + +} // end ns + +namespace conversion_operator { +void test() { + auto L = [](auto a) -> int { return a; }; + int (*fp)(int) = L; + int (&fp2)(int) = [](auto a) { return a; }; // expected-error{{non-const lvalue}} + int (&&fp3)(int) = [](auto a) { return a; }; // expected-error{{no viable conversion}}\ + //expected-note{{candidate}} + } +} +} + +namespace return_type_deduction_ok { + auto l = [](auto a) ->auto { return a; }(2); + auto l2 = [](auto a) ->decltype(auto) { return a; }(2); + auto l3 = [](auto a) { return a; }(2); + +} + +namespace generic_lambda_as_default_argument_ok { + void test(int i = [](auto a)->int { return a; }(3)) { + } +} + +namespace nested_non_capturing_lambda_tests { +template<class ... Ts> void print(Ts ...) { } +int test() { +{ + auto L = [](auto a) { + return [](auto b) { + return b; + }; + }; + auto M = L(3); + M(4.15); + } +{ + int i = 10; //expected-note 3{{declared here}} + auto L = [](auto a) { + return [](auto b) { //expected-note 3{{begins here}} + i = b; //expected-error 3{{cannot be implicitly captured}} + return b; + }; + }; + auto M = L(3); //expected-note{{instantiation}} + M(4.15); //expected-note{{instantiation}} + } + { + int i = 10; + auto L = [](auto a) { + return [](auto b) { + b = sizeof(i); //ok + return b; + }; + }; + } + { + auto L = [](auto a) { + print("a = ", a, "\n"); + return [](auto b) ->decltype(a) { + print("b = ", b, "\n"); + return b; + }; + }; + auto M = L(3); + M(4.15); + } + +{ + auto L = [](auto a) ->decltype(a) { + print("a = ", a, "\n"); + return [](auto b) ->decltype(a) { //expected-error{{no viable conversion}}\ + //expected-note{{candidate template ignored}} + print("b = ", b, "\n"); + return b; + }; + }; + auto M = L(3); //expected-note{{in instantiation of}} + } +{ + auto L = [](auto a) { + print("a = ", a, "\n"); + return [](auto ... b) ->decltype(a) { + print("b = ", b ..., "\n"); + return 4; + }; + }; + auto M = L(3); + M(4.15, 3, "fv"); +} + +{ + auto L = [](auto a) { + print("a = ", a, "\n"); + return [](auto ... b) ->decltype(a) { + print("b = ", b ..., "\n"); + return 4; + }; + }; + auto M = L(3); + int (*fp)(double, int, const char*) = M; + fp(4.15, 3, "fv"); +} + +{ + auto L = [](auto a) { + print("a = ", a, "\n"); + return [](char b) { + return [](auto ... c) ->decltype(b) { + print("c = ", c ..., "\n"); + return 42; + }; + }; + }; + L(4); + auto M = L(3); + M('a'); + auto N = M('x'); + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + char (*np)(const char*, int, const char*, double, const char*, int) = N; + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +} + + +{ + auto L = [](auto a) { + print("a = ", a, "\n"); + return [](decltype(a) b) { + return [](auto ... c) ->decltype(b) { + print("c = ", c ..., "\n"); + return 42; + }; + }; + }; + L('4'); + auto M = L('3'); + M('a'); + auto N = M('x'); + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + char (*np)(const char*, int, const char*, double, const char*, int) = N; + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +} + + +{ + struct X { + static void foo(double d) { } + void test() { + auto L = [](auto a) { + print("a = ", a, "\n"); + foo(a); + return [](decltype(a) b) { + foo(b); + foo(sizeof(a) + sizeof(b)); + return [](auto ... c) ->decltype(b) { + print("c = ", c ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return 42; + }; + }; + }; + L('4'); + auto M = L('3'); + M('a'); + auto N = M('x'); + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + char (*np)(const char*, int, const char*, double, const char*, int) = N; + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + } +}; +X x; +x.test(); +} +// Make sure we can escape the function +{ + struct X { + static void foo(double d) { } + auto test() { + auto L = [](auto a) { + print("a = ", a, "\n"); + foo(a); + return [](decltype(a) b) { + foo(b); + foo(sizeof(a) + sizeof(b)); + return [](auto ... c) ->decltype(b) { + print("c = ", c ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return 42; + }; + }; + }; + return L; + } +}; + X x; + auto L = x.test(); + L('4'); + auto M = L('3'); + M('a'); + auto N = M('x'); + N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + char (*np)(const char*, int, const char*, double, const char*, int) = N; + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +} + +{ + struct X { + static void foo(double d) { } + auto test() { + auto L = [](auto a) { + print("a = ", a, "\n"); + foo(a); + return [](decltype(a) b) { + foo(b); + foo(sizeof(a) + sizeof(b)); + return [](auto ... c) { + print("c = ", c ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} + print("d = ", d ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return decltype(a){}; + }; + }; + }; + }; + return L; + } +}; + X x; + auto L = x.test(); + L('4'); + auto M = L('3'); + M('a'); + auto N = M('x'); + auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + char (*np)(const char*, int, const char*, double, const char*, int) = O; + np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); + int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} + +} +} // end test() + +namespace wrapped_within_templates { + +namespace explicit_return { +template<class T> int fooT(T t) { + auto L = [](auto a) -> void { + auto M = [](char b) -> void { + auto N = [](auto c) -> void { + int x = 0; + x = sizeof(a); + x = sizeof(b); + x = sizeof(c); + }; + N('a'); + N(decltype(a){}); + }; + }; + L(t); + L(3.14); + return 0; +} + +int run = fooT('a') + fooT(3.14); + +} // end explicit_return + +namespace implicit_return_deduction { +template<class T> auto fooT(T t) { + auto L = [](auto a) { + auto M = [](char b) { + auto N = [](auto c) { + int x = 0; + x = sizeof(a); + x = sizeof(b); + x = sizeof(c); + }; + N('a'); + N(decltype(a){}); + }; + }; + L(t); + L(3.14); + return 0; +} + +int run = fooT('a') + fooT(3.14); + +template<class ... Ts> void print(Ts ... ts) { } + +template<class F, class ... Rest> using first = F; + +template<class ... Ts> auto fooV(Ts ... ts) { + auto L = [](auto ... a) { + auto M = [](decltype(a) ... b) { + auto N = [](auto c) { + int x = 0; + x = sizeof...(a); + x = sizeof...(b); + x = sizeof(c); + }; + N('a'); + N(N); + N(first<Ts...>{}); + }; + M(a...); + print("a = ", a..., "\n"); + }; + L(L, ts...); + print("ts = ", ts..., "\n"); + return 0; +} + +int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{}); + +} //implicit_return_deduction + + +} //wrapped_within_templates + +namespace at_ns_scope { + void foo(double d) { } + auto test() { + auto L = [](auto a) { + print("a = ", a, "\n"); + foo(a); + return [](decltype(a) b) { + foo(b); + foo(sizeof(a) + sizeof(b)); + return [](auto ... c) { + print("c = ", c ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} + print("d = ", d ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return decltype(a){}; + }; + }; + }; + }; + return L; + } +auto L = test(); +auto L_test = L('4'); +auto M = L('3'); +auto M_test = M('a'); +auto N = M('x'); +auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +char (*np)(const char*, int, const char*, double, const char*, int) = O; +auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} + + + +} + +namespace variadic_tests_1 { +template<class ... Ts> void print(Ts ... ts) { } + +template<class F, class ... Rest> using FirstType = F; +template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; } + +template<class ... Ts> int fooV(Ts ... ts) { + auto L = [](auto ... a) -> void { + auto M = [](decltype(a) ... b) -> void { + auto N = [](auto c) -> void { + int x = 0; + x = sizeof...(a); + x = sizeof...(b); + x = sizeof(c); + }; + N('a'); + N(N); + N(FirstType<Ts...>{}); + }; + M(a...); + print("a = ", a..., "\n"); + }; + L(L, ts...); + print("ts = ", ts..., "\n"); + return 0; +} + +int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{}); + +namespace more_variadic_1 { + +template<class ... Ts> int fooV(Ts ... ts) { + auto L = [](auto ... a) { + auto M = [](decltype(a) ... b) -> void { + auto N = [](auto c) -> void { + int x = 0; + x = sizeof...(a); + x = sizeof...(b); + x = sizeof(c); + }; + N('a'); + N(N); + N(FirstType<Ts...>{}); + }; + M(a...); + return M; + }; + auto M = L(L, ts...); + decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L; + void (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...); + + { + auto L = [](auto ... a) { + auto M = [](decltype(a) ... b) { + auto N = [](auto c) -> void { + int x = 0; + x = sizeof...(a); + x = sizeof...(b); + x = sizeof(c); + }; + N('a'); + N(N); + N(FirstType<Ts...>{}); + return N; + }; + M(a...); + return M; + }; + auto M = L(L, ts...); + decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L; + fp(L, ts...); + decltype(L(L, ts...)(L, ts...)) (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...); + fp2 = fp(L, ts...); + void (*fp3)(char) = fp2(L, ts...); + fp3('a'); + } + return 0; +} + +int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{}); + + +} //end ns more_variadic_1 + +} // end ns variadic_tests_1 + +namespace at_ns_scope_within_class_member { + struct X { + static void foo(double d) { } + auto test() { + auto L = [](auto a) { + print("a = ", a, "\n"); + foo(a); + return [](decltype(a) b) { + foo(b); + foo(sizeof(a) + sizeof(b)); + return [](auto ... c) { + print("c = ", c ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} + print("d = ", d ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return decltype(a){}; + }; + }; + }; + }; + return L; + } +}; +X x; +auto L = x.test(); +auto L_test = L('4'); +auto M = L('3'); +auto M_test = M('a'); +auto N = M('x'); +auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +char (*np)(const char*, int, const char*, double, const char*, int) = O; +auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} + +} //end at_ns_scope_within_class_member + + +namespace at_ns_scope_within_class_template_member { + struct X { + static void foo(double d) { } + template<class T = int> + auto test(T = T{}) { + auto L = [](auto a) { + print("a = ", a, "\n"); + foo(a); + return [](decltype(a) b) { + foo(b); + foo(sizeof(a) + sizeof(b)); + return [](auto ... c) { + print("c = ", c ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} + print("d = ", d ..., "\n"); + foo(decltype(b){}); + foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); + return decltype(a){}; + }; + }; + }; + }; + return L; + } + +}; +X x; +auto L = x.test(); +auto L_test = L('4'); +auto M = L('3'); +auto M_test = M('a'); +auto N = M('x'); +auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +char (*np)(const char*, int, const char*, double, const char*, int) = O; +auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); +int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} + +} //end at_ns_scope_within_class_member + + +namespace nested_generic_lambdas_123 { +void test() { + auto L = [](auto a) -> int { + auto M = [](auto b, decltype(a) b2) -> int { + return 1; + }; + M(a, a); + }; + L(3); +} +template<class T> void foo(T) { + auto L = [](auto a) { return a; }; +} +template void foo(int); +} // end ns nested_generic_lambdas_123 + +namespace nested_fptr_235 { +int test() +{ + auto L = [](auto b) { + return [](auto a) ->decltype(a) { return a; }; + }; + int (*fp)(int) = L(8); + fp(5); + L(3); + char (*fc)(char) = L('a'); + fc('b'); + L('c'); + double (*fd)(double) = L(3.14); + fd(3.14); + fd(6.26); + return 0; +} +int run = test(); +} + + +namespace fptr_with_decltype_return_type { +template<class F, class ... Ts> using FirstType = F; +template<class F, class ... Rest> F& FirstArg(F& f, Rest& ... r) { return f; }; +template<class ... Ts> auto vfun(Ts&& ... ts) { + print(ts...); + return FirstArg(ts...); +} +int test() +{ + { + auto L = [](auto ... As) { + return [](auto b) ->decltype(b) { + vfun([](decltype(As) a) -> decltype(a) { return a; } ...)(FirstType<decltype(As)...>{}); + return decltype(b){}; + }; + }; + auto LL = L(1, 'a', 3.14, "abc"); + LL("dim"); + } + return 0; +} +int run = test(); +} + +} // end ns nested_non_capturing_lambda_tests + +namespace PR17476 { +struct string { + string(const char *__s) { } + string &operator+=(const string &__str) { return *this; } +}; + +template <class T> +void finalizeDefaultAtomValues() { + auto startEnd = [](const char * sym) -> void { + string start("__"); + start += sym; + }; + startEnd("preinit_array"); +} + +void f() { finalizeDefaultAtomValues<char>(); } + +} + +namespace PR17476_variant { +struct string { + string(const char *__s) { } + string &operator+=(const string &__str) { return *this; } +}; + +template <class T> +void finalizeDefaultAtomValues() { + auto startEnd = [](const T *sym) -> void { + string start("__"); + start += sym; + }; + startEnd("preinit_array"); +} + +void f() { finalizeDefaultAtomValues<char>(); } + +} + +namespace PR17877_lambda_declcontext_and_get_cur_lambda_disconnect { + + +template<class T> struct U { + int t = 0; +}; + +template<class T> +struct V { + U<T> size() const { return U<T>{}; } +}; + +template<typename T> +void Do() { + V<int> v{}; + [=] { v.size(); }; +} + +} + +namespace inclass_lambdas_within_nested_classes { +namespace ns1 { + +struct X1 { + struct X2 { + enum { E = [](auto i) { return i; }(3) }; //expected-error{{inside of a constant expression}}\ + //expected-error{{not an integral constant}} + int L = ([] (int i) { return i; })(2); + void foo(int i = ([] (int i) { return i; })(2)) { } + int B : ([](int i) { return i; })(3); //expected-error{{inside of a constant expression}}\ + //expected-error{{not an integral constant}} + int arr[([](int i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\ + //expected-error{{must have a constant size}} + int (*fp)(int) = [](int i) { return i; }; + void fooptr(int (*fp)(char) = [](char c) { return 0; }) { } + int L2 = ([](auto i) { return i; })(2); + void fooG(int i = ([] (auto i) { return i; })(2)) { } + int BG : ([](auto i) { return i; })(3); //expected-error{{inside of a constant expression}} \ + //expected-error{{not an integral constant}} + int arrG[([](auto i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\ + //expected-error{{must have a constant size}} + int (*fpG)(int) = [](auto i) { return i; }; + void fooptrG(int (*fp)(char) = [](auto c) { return 0; }) { } + }; +}; +} //end ns + +namespace ns2 { +struct X1 { + template<class T> + struct X2 { + int L = ([] (T i) { return i; })(2); + void foo(int i = ([] (int i) { return i; })(2)) { } + int B : ([](T i) { return i; })(3); //expected-error{{inside of a constant expression}}\ + //expected-error{{not an integral constant}} + int arr[([](T i) { return i; })(3)]; //expected-error{{inside of a constant expression}}\ + //expected-error{{must have a constant size}} + int (*fp)(T) = [](T i) { return i; }; + void fooptr(T (*fp)(char) = [](char c) { return 0; }) { } + int L2 = ([](auto i) { return i; })(2); + void fooG(T i = ([] (auto i) { return i; })(2)) { } + int BG : ([](auto i) { return i; })(3); //expected-error{{not an integral constant}} + int arrG[([](auto i) { return i; })(3)]; //expected-error{{must have a constant size}} + int (*fpG)(T) = [](auto i) { return i; }; + void fooptrG(T (*fp)(char) = [](auto c) { return 0; }) { } + template<class U = char> int fooG2(T (*fp)(U) = [](auto a) { return 0; }) { return 0; } + template<class U = char> int fooG3(T (*fp)(U) = [](auto a) { return 0; }); + }; +}; +template<class T> +template<class U> +int X1::X2<T>::fooG3(T (*fp)(U)) { return 0; } +X1::X2<int> x2; //expected-note 3{{in instantiation of}} +int run1 = x2.fooG2(); +int run2 = x2.fooG3(); +} // end ns + + + +} //end ns inclass_lambdas_within_nested_classes
\ No newline at end of file diff --git a/test/SemaCXX/cxx1y-init-captures.cpp b/test/SemaCXX/cxx1y-init-captures.cpp new file mode 100644 index 0000000..2cb4d31 --- /dev/null +++ b/test/SemaCXX/cxx1y-init-captures.cpp @@ -0,0 +1,169 @@ +// RUN: %clang_cc1 -std=c++1y %s -verify -emit-llvm-only + +namespace variadic_expansion { + int f(int &, char &) { return 0; } + template<class ... Ts> char fv(Ts ... ts) { return 0; } + // FIXME: why do we get 2 error messages + template <typename ... T> void g(T &... t) { //expected-note3{{declared here}} + f([&a(t)]()->decltype(auto) { + return a; + }() ...); + + auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; }; + const int y = 10; + auto M = [x = y, + &z = y](T& ... t) { }; + auto N = [x = y, + &z = y, n = f(t...), + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) { + fv([&a(t)]()->decltype(auto) { + return a; + }() ...); + }; + auto N2 = [x = y, //expected-note3{{begins here}} + &z = y, n = f(t...), + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { + fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}} + return a; + }() ...); + }; + + } + + void h(int i, char c) { g(i, c); } //expected-note{{in instantiation}} +} + +namespace odr_use_within_init_capture { + +int test() { + + { // no captures + const int x = 10; + auto L = [z = x + 2](int a) { + auto M = [y = x - 2](char b) { + return y; + }; + return M; + }; + + } + { // should not capture + const int x = 10; + auto L = [&z = x](int a) { + return a;; + }; + + } + { + const int x = 10; + auto L = [k = x](char a) { //expected-note {{declared}} + return [](int b) { //expected-note {{begins}} + return [j = k](int c) { //expected-error {{cannot be implicitly captured}} + return c; + }; + }; + }; + } + { + const int x = 10; + auto L = [k = x](char a) { + return [=](int b) { + return [j = k](int c) { + return c; + }; + }; + }; + } + { + const int x = 10; + auto L = [k = x](char a) { + return [k](int b) { + return [j = k](int c) { + return c; + }; + }; + }; + } + + return 0; +} + +int run = test(); + +} + +namespace odr_use_within_init_capture_template { + +template<class T = int> +int test(T t = T{}) { + + { // no captures + const T x = 10; + auto L = [z = x](char a) { + auto M = [y = x](T b) { + return y; + }; + return M; + }; + + } + { // should not capture + const T x = 10; + auto L = [&z = x](T a) { + return a;; + }; + + } + { // will need to capture x in outer lambda + const T x = 10; //expected-note {{declared}} + auto L = [z = x](char a) { //expected-note {{begins}} + auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}} + return y; + }; + return M; + }; + + } + { // will need to capture x in outer lambda + const T x = 10; + auto L = [=,z = x](char a) { + auto M = [&y = x](T b) { + return y; + }; + return M; + }; + + } + { // will need to capture x in outer lambda + const T x = 10; + auto L = [x, z = x](char a) { + auto M = [&y = x](T b) { + return y; + }; + return M; + }; + } + { // will need to capture x in outer lambda + const int x = 10; //expected-note 2{{declared}} + auto L = [z = x](char a) { //expected-note 2{{begins}} + auto M = [&y = x](T b) { //expected-error 2{{cannot be implicitly captured}} + return y; + }; + return M; + }; + } + { + // no captures + const T x = 10; + auto L = [z = + [z = x, &y = x](char a) { return z + y; }('a')](char a) + { return z; }; + + } + + return 0; +} + +int run = test(); //expected-note {{instantiation}} + +}
\ No newline at end of file diff --git a/test/SemaCXX/cxx1y-sized-deallocation.cpp b/test/SemaCXX/cxx1y-sized-deallocation.cpp new file mode 100644 index 0000000..81a8eeb --- /dev/null +++ b/test/SemaCXX/cxx1y-sized-deallocation.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++1y -verify %s -fsized-deallocation -fexceptions -fcxx-exceptions + +using size_t = decltype(sizeof(0)); + +void f(void *p, void *q) { + // OK, implicitly declared. + operator delete(p, 8); + operator delete[](q, 12); + static_assert(noexcept(operator delete(p, 8)), ""); + static_assert(noexcept(operator delete[](q, 12)), ""); +} + +void *operator new(size_t bad, size_t idea); +struct S { S() { throw 0; } }; +void g() { + new (123) S; // expected-error {{'new' expression with placement arguments refers to non-placement 'operator delete'}} +} diff --git a/test/SemaCXX/cxx1y-user-defined-literals.cpp b/test/SemaCXX/cxx1y-user-defined-literals.cpp new file mode 100644 index 0000000..fa4ff03 --- /dev/null +++ b/test/SemaCXX/cxx1y-user-defined-literals.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++1y %s -include %s -verify + +#ifndef INCLUDED +#define INCLUDED + +#pragma clang system_header +namespace std { + using size_t = decltype(sizeof(0)); + + struct duration {}; + duration operator""ns(unsigned long long); + duration operator""us(unsigned long long); + duration operator""ms(unsigned long long); + duration operator""s(unsigned long long); + duration operator""min(unsigned long long); + duration operator""h(unsigned long long); + + struct string {}; + string operator""s(const char*, size_t); + + template<typename T> struct complex {}; + complex<float> operator""if(long double); + complex<float> operator""if(unsigned long long); + complex<double> operator""i(long double); + complex<double> operator""i(unsigned long long); + complex<long double> operator""il(long double); + complex<long double> operator""il(unsigned long long); +} + +#else + +using namespace std; +duration a = 1ns, b = 1us, c = 1ms, d = 1s, e = 1min, f = 1h; +string s = "foo"s; +char error = 'x's; // expected-error {{invalid suffix}} expected-error {{expected ';'}} + +int _1z = 1z; // expected-error {{invalid suffix}} +int _1b = 1b; // expected-error {{invalid digit}} + +complex<float> cf1 = 1if, cf2 = 2.if, cf3 = 0x3if; +complex<double> cd1 = 1i, cd2 = 2.i, cd3 = 0b0110101i; +complex<long double> cld1 = 1il, cld2 = 2.il, cld3 = 0047il; + +#endif diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp new file mode 100644 index 0000000..94d0f16 --- /dev/null +++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -0,0 +1,299 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -DPRECXX11 +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s + +#define CONST const + +#ifdef PRECXX11 +#define static_assert(expr, msg) typedef int static_assert[(expr) ? 1 : -1]; +#endif + +class A { + template<typename T> CONST T wrong; // expected-error {{member 'wrong' declared as a template}} + template<typename T> CONST T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}} + template<typename T, typename T0> static CONST T right = T(100); + template<typename T> static CONST T right<T,int> = 5; + template<typename T> CONST int right<int,T>; // expected-error {{member 'right' declared as a template}} + template<typename T> CONST float right<float,T> = 5; // expected-error {{member 'right' declared as a template}} + template<> static CONST int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}} + template<> static CONST float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}} + template static CONST int right<int,int>; // expected-error {{template specialization requires 'template<>'}} \ + // expected-error {{explicit specialization of 'right' in class scope}} +}; + +namespace out_of_line { + class B0 { + template<typename T, typename T0> static CONST T right = T(100); + template<typename T> static CONST T right<T,int> = T(5); + }; + template<> CONST int B0::right<int,int> = 7; + template CONST int B0::right<int,int>; + template<> CONST int B0::right<int,float>; + template CONST int B0::right<int,float>; + + class B1 { + template<typename T, typename T0> static CONST T right; + template<typename T> static CONST T right<T,int>; + }; + template<typename T, typename T0> CONST T B1::right = T(100); + template<typename T> CONST T B1::right<T,int> = T(5); + + class B2 { + template<typename T, typename T0> static CONST T right = T(100); // expected-note {{previous definition is here}} + template<typename T> static CONST T right<T,int> = T(5); // expected-note {{previous definition is here}} + }; + template<typename T, typename T0> CONST T B2::right = T(100); // expected-error {{redefinition of 'right'}} + template<typename T> CONST T B2::right<T,int> = T(5); // expected-error {{redefinition of 'right'}} + + class B3 { + template<typename T, typename T0> static CONST T right = T(100); + template<typename T> static CONST T right<T,int> = T(5); + }; + template<typename T, typename T0> CONST T B3::right; + template<typename T> CONST T B3::right<T,int>; + + class B4 { + template<typename T, typename T0> static CONST T a; + template<typename T> static CONST T a<T,int> = T(100); + template<typename T, typename T0> static CONST T b = T(100); + template<typename T> static CONST T b<T,int>; + }; + template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}} + template<typename T> CONST T B4::a<T,int>; + template CONST int B4::a<int,char>; // expected-note {{in instantiation of}} + template CONST int B4::a<int,int>; + + template<typename T, typename T0> CONST T B4::b; + template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}} + template CONST int B4::b<int,char>; + template CONST int B4::b<int,int>; // expected-note {{in instantiation of}} +} + +namespace non_const_init { + class A { + template<typename T> static T wrong_inst_undefined = T(10); // expected-note {{refers here}} + template<typename T> static T wrong_inst_defined = T(10); // expected-error {{non-const static data member must be initialized out of line}} + template<typename T> static T wrong_inst_out_of_line; + }; + + template const int A::wrong_inst_undefined<const int>; // expected-error {{undefined}} + + template<typename T> T A::wrong_inst_defined; + template const int A::wrong_inst_defined<const int>; + template int A::wrong_inst_defined<int>; // expected-note {{in instantiation of static data member 'non_const_init::A::wrong_inst_defined<int>' requested here}} + + template<typename T> T A::wrong_inst_out_of_line = T(10); + template int A::wrong_inst_out_of_line<int>; + + class B { + template<typename T> static T wrong_inst; // expected-note {{refers here}} + template<typename T> static T wrong_inst<T*> = T(100); // expected-error {{non-const static data member must be initialized out of line}} expected-note {{refers here}} + + template<typename T> static T wrong_inst_fixed; + template<typename T> static T wrong_inst_fixed<T*>; + }; + template int B::wrong_inst<int>; // expected-error {{undefined}} + // FIXME: It'd be better to produce the 'explicit instantiation of undefined + // template' diagnostic here, not the 'must be initialized out of line' + // diagnostic. + template int B::wrong_inst<int*>; // expected-note {{in instantiation of static data member 'non_const_init::B::wrong_inst<int *>' requested here}} + template const int B::wrong_inst<const int*>; // expected-error {{undefined}} + template<typename T> T B::wrong_inst_fixed = T(100); + template int B::wrong_inst_fixed<int>; + + class C { + template<typename T> static CONST T right_inst = T(10); // expected-note {{here}} + template<typename T> static CONST T right_inst<T*> = T(100); // expected-note {{here}} + }; + template CONST int C::right_inst<int>; // expected-error {{undefined variable template}} + template CONST int C::right_inst<int*>; // expected-error {{undefined variable template}} + + namespace pointers { + + struct C0 { + template<typename U> static U Data; + template<typename U> static CONST U Data<U*> = U(); // expected-note {{here}} + + template<typename U> static U Data2; + template<typename U> static CONST U Data2<U*> = U(); + }; + const int c0_test = C0::Data<int*>; + static_assert(c0_test == 0, ""); + template const int C0::Data<int*>; // expected-error {{undefined}} + + template<typename U> const U C0::Data2<U*>; + template const int C0::Data2<int*>; + + struct C1a { + template<typename U> static U Data; + template<typename U> static U* Data<U*>; // Okay, with out-of-line definition + }; + template<typename T> T* C1a::Data<T*> = new T(); + template int* C1a::Data<int*>; + + struct C1b { + template<typename U> static U Data; + template<typename U> static CONST U* Data<U*>; // Okay, with out-of-line definition + }; + template<typename T> CONST T* C1b::Data<T*> = (T*)(0); + template CONST int* C1b::Data<int*>; + + struct C2a { + template<typename U> static int Data; + template<typename U> static U* Data<U*> = new U(); // expected-error {{non-const static data member must be initialized out of line}} + }; + template int* C2a::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int *>' requested here}} + + struct C2b { + template<typename U> static int Data; + template<typename U> static U *const Data<U*> = (U*)(0); // expected-error {{static data member of type 'int *const'}} + }; + template<typename U> U *const C2b::Data<U*>; + template int *const C2b::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int *>' requested here}} + } +} + +#ifndef PRECXX11 +namespace constexpred { + class A { + template<typename T> constexpr T wrong; // expected-error {{member 'wrong' declared as a template}} \ + // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}} + template<typename T> constexpr T wrong_init = 5; // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}} + template<typename T, typename T0> static constexpr T right = T(100); + template<typename T> static constexpr T right<T,int> = 5; + template<typename T> constexpr int right<int,T>; // expected-error {{member 'right' declared as a template}} \ + // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}} + template<typename T> constexpr float right<float,T> = 5; // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}} + template<> static constexpr int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}} + template<> static constexpr float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}} + template static constexpr int right<int,int>; // expected-error {{template specialization requires 'template<>'}} \ + // expected-error {{explicit specialization of 'right' in class scope}} + }; +} +#endif + +namespace in_class_template { + + template<typename T> + class D0 { + template<typename U> static U Data; // expected-note {{here}} + template<typename U> static CONST U Data<U*> = U(); + }; + template CONST int D0<float>::Data<int*>; + template int D0<float>::Data<int>; // expected-error {{undefined}} + template<typename T> template<typename U> const U D0<T>::Data<U*>; + + template<typename T> + class D1 { + template<typename U> static U Data; + template<typename U> static U* Data<U*>; + }; + template<typename T> + template<typename U> U* D1<T>::Data<U*> = (U*)(0); + template int* D1<float>::Data<int*>; // expected-note {{previous}} + template int* D1<float>::Data<int*>; // expected-error {{duplicate explicit instantiation}} + + template<typename T> + class D2 { + template<typename U> static U Data; + template<typename U> static U* Data<U*>; + }; + template<> + template<typename U> U* D2<float>::Data<U*> = (U*)(0) + 1; + template int* D2<float>::Data<int*>; // expected-note {{previous}} + template int* D2<float>::Data<int*>; // expected-error {{duplicate explicit instantiation}} + + template<typename T> + struct D3 { + template<typename U> static CONST U Data = U(100); // expected-note {{here}} + }; + static_assert(D3<float>::Data<int> == 100, ""); + template const char D3<float>::Data<char>; // expected-error {{undefined}} + + namespace bug_files { + template<typename T> + class D0a { + template<typename U> static U Data; + template<typename U> static CONST U Data<U*> = U(10); // expected-note {{previous definition is here}} + }; + template<> + template<typename U> U D0a<float>::Data<U*> = U(100); // expected-error {{redefinition of 'Data'}} + + // FIXME: We should accept this, and the corresponding case for class + // templates. + // + // [temp.class.spec.mfunc]/2: If the primary member template is explicitly + // specialized for a given specialization of the enclosing class template, + // the partial specializations of the member template are ignored + template<typename T> + class D1 { + template<typename U> static U Data; + template<typename U> static CONST U Data<U*> = U(10); // expected-note {{previous definition is here}} + }; + template<> + template<typename U> U D1<float>::Data = U(10); + template<> + template<typename U> U D1<float>::Data<U*> = U(100); // expected-error{{redefinition of 'Data'}} + } + + namespace definition_after_outer_instantiation { + template<typename A> struct S { + template<typename B> static const int V1; + template<typename B> static const int V2; + }; + template struct S<int>; + template<typename A> template<typename B> const int S<A>::V1 = 123; + template<typename A> template<typename B> const int S<A>::V2<B*> = 456; + + static_assert(S<int>::V1<int> == 123, ""); + + // FIXME: The first and third case below possibly should be accepted. We're + // not picking up partial specializations added after the primary template + // is instantiated. This is kind of implied by [temp.class.spec.mfunc]/2, + // and matches our behavior for member class templates, but it's not clear + // that this is intentional. See PR17294 and core-24030. + static_assert(S<int>::V2<int*> == 456, ""); // FIXME expected-error {{}} + static_assert(S<int>::V2<int&> == 789, ""); // expected-error {{}} + + template<typename A> template<typename B> const int S<A>::V2<B&> = 789; + static_assert(S<int>::V2<int&> == 789, ""); // FIXME expected-error {{}} + + // All is OK if the partial specialization is declared before the implicit + // instantiation of the class template specialization. + static_assert(S<char>::V1<int> == 123, ""); + static_assert(S<char>::V2<int*> == 456, ""); + static_assert(S<char>::V2<int&> == 789, ""); + } + + namespace incomplete_array { + template<typename T> extern T var[]; + template<typename T> T var[] = { 1, 2, 3 }; + template<> char var<char>[] = "hello"; + template<typename T> char var<T*>[] = "pointer"; + + static_assert(sizeof(var<int>) == 12, ""); + static_assert(sizeof(var<char>) == 6, ""); + static_assert(sizeof(var<void*>) == 8, ""); + + template<typename...> struct tuple; + + template<typename T> struct A { + template<typename U> static T x[]; + template<typename U> static T y[]; + + template<typename...U> static T y<tuple<U...> >[]; + }; + + int *use_before_definition = A<int>::x<char>; + template<typename T> template<typename U> T A<T>::x[sizeof(U)]; + static_assert(sizeof(A<int>::x<char>) == 4, ""); + + template<typename T> template<typename...U> T A<T>::y<tuple<U...> >[] = { U()... }; + static_assert(sizeof(A<int>::y<tuple<char, char, char> >) == 12, ""); + } +} + +namespace in_nested_classes { + // TODO: +} + diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp new file mode 100644 index 0000000..b6e8762 --- /dev/null +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -0,0 +1,434 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11 +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s + +#ifdef PRECXX11 + #define CONST const +#else + #define CONST constexpr +#endif + +template<typename T> +T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} + +template<typename T> +CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}} + +template<typename T> extern CONST T vc; +#ifndef PRECXX11 +// expected-error@-2 {{constexpr variable declaration must be a definition}} +#endif + +namespace use_in_top_level_funcs { + + void good() { + int ipi = pi<int>; + int icpi = cpi<int>; + double dpi = pi<double>; + double dcpi = cpi<double>; + } + + void no_deduce() { + // template arguments are not deduced for uses of variable templates. + int ipi = pi; // expected-error {{cannot refer to variable template 'pi' without a template argument list}} + int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}} + } + + template<typename T> + T circular_area(T r) { + return pi<T> * r * r; + } + + template<typename T> + CONST T const_circular_area(T r) { + return cpi<T> * r * r; + } + + double use_circular_area(double r) { + CONST float t = const_circular_area(2.0) - 12; +#ifndef PRECXX11 + static_assert(const_circular_area(2) == 12, ""); + CONST int test = (t > 0) && (t < 1); + static_assert(test, ""); +#endif + return circular_area(r); + } +} + +namespace shadow { + void foo() { + int ipi0 = pi<int>; + int pi; + int a = pi; + int ipi = pi<int>; // expected-error {{expected '(' for function-style cast or type construction}} \ + // expected-error {{expected expression}} + } +} + +namespace odr_tmpl { + namespace pv_cvt { + int v; // expected-note {{previous definition is here}} + template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}} + } + namespace pvt_cv { + template<typename T> T v; // expected-note {{previous definition is here}} + int v; // expected-error {{redefinition of 'v' as different kind of symbol}} + } + namespace pvt_cvt { + template<typename T> T v0; // expected-note {{previous definition is here}} + template<typename T> T v0; // expected-error {{redefinition of 'v0'}} + + template<typename T> T v; // expected-note {{previous definition is here}} + template<typename T> int v; // expected-error {{redefinition of 'v'}} + + template<typename T> int v1; // expected-note {{previous template declaration is here}} + template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}} + } + namespace pvt_use { + template<typename T> T v; + v = 10; // expected-error {{C++ requires a type specifier for all declarations}} + } + + namespace pvt_diff_params { + // FIXME: (?) Redefinitions should simply be not allowed, whether the + // template parameters match or not. However, this current behaviour also + // matches that of class templates... + template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}} + template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} + template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}} + } + + namespace pvt_extern { + template<typename T> T v = T(); + template<typename T> extern T v; // redeclaration is allowed \ + // expected-note {{previous definition is here}} + template<typename T> extern int v; // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}} + +#ifndef PRECXX11 + template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}} +#endif + + template<typename T> T var = T(); // expected-note {{previous definition is here}} + extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}} + } + +#ifndef PRECXX11 + namespace pvt_auto { + template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}} + template<typename T> auto v1 = T(); // expected-note {{previous definition is here}} + template<typename T> int v1; // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}} + template<typename T> auto v2 = T(); // expected-note {{previous definition is here}} + template<typename T> T v2; // expected-error {{redefinition of 'v2'}} + template<typename T> auto v3 = T(); // expected-note {{previous definition is here}} + template<typename T> extern T v3; // expected-error {{redefinition of 'v3' with a different type: 'T' vs 'auto'}} + template<typename T> auto v4 = T(); + template<typename T> extern auto v4; // expected-error {{declaration of variable 'v4' with type 'auto' requires an initializer}} + } +#endif + +} + +namespace explicit_instantiation { + template<typename T> + T pi0a = T(3.1415926535897932385); // expected-note {{variable template 'pi0a' declared here}} + template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}} + + template<typename T> + T pi0b = T(3.1415926535897932385); // expected-note {{variable template 'pi0b' declared here}} + template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}} + + template<typename T> + T pi0c = T(3.1415926535897932385); // expected-note {{variable template 'pi0c' declared here}} + template int pi0c<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}} + + template<typename T> + T pi0 = T(3.1415926535897932385); + template int pi0<int>; // expected-note {{previous explicit instantiation is here}} + template int pi0<int>; // expected-error {{duplicate explicit instantiation of 'pi0<int>'}} + + template<typename T> + CONST T pi1a = T(3.1415926535897932385); // expected-note {{variable template 'pi1a' declared here}} + template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}} + + template<typename T> + CONST T pi1b = T(3.1415926535897932385); // expected-note {{variable template 'pi1b' declared here}} + template int pi1b<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}} + + template<typename T> + CONST T pi1 = T(3.1415926535897932385); + template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}} + template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}} + +#ifndef PRECXX11 + namespace auto_var { + template<typename T> auto var0 = T(); + template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}} + + template<typename T> auto var = T(); + template int var<int>; + } +#endif + + template<typename=int> int missing_args; // expected-note {{here}} + template int missing_args; // expected-error {{must specify a template argument list}} + + namespace extern_var { + // TODO: + } +} + +namespace explicit_specialization { + + namespace good { + template<typename T1, typename T2> + CONST int pi2 = 1; + + template<typename T> + CONST int pi2<T,int> = 2; + + template<typename T> + CONST int pi2<int,T> = 3; + + template<> CONST int pi2<int,int> = 4; + +#ifndef PRECXX11 + void foo() { + static_assert(pi2<int,int> == 4, ""); + static_assert(pi2<float,int> == 2, ""); + static_assert(pi2<int,float> == 3, ""); + static_assert(pi2<int,float> == pi2<int,double>, ""); + static_assert(pi2<float,float> == 1, ""); + static_assert(pi2<float,float> == pi2<float,double>, ""); + } +#endif + } + + namespace ambiguous { + + template<typename T1, typename T2> + CONST int pi2 = 1; + + template<typename T> + CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}} + + template<typename T> + CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}} + + void foo() { + int a = pi2<int,int>; // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}} + } + } + + namespace type_changes { + + template<typename T> + T pi0 = T(3.1415926535897932385); + + template<> float pi0<int> = 10; + template<> int pi0<const int> = 10; + + template<typename T> + T pi1 = T(3.1415926535897932385); + template<> CONST int pi1<int> = 10; + + template<typename T> + T pi2 = T(3.1415926535897932385); + template<> int pi2<const int> = 10; + + template<typename T> + CONST T pi4 = T(3.1415926535897932385); + template<> int pi4<int> = 10; + } + + namespace redefinition { + template<typename T> + T pi0 = T(3.1415926535897932385); + + template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}} +#ifndef PRECXX11 +// expected-note@-2 {{previous definition is here}} +#endif + template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} + template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}} + template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}} +#ifndef PRECXX11 + template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} +#endif + + + template<typename T> + CONST T pi1 = T(3.1415926535897932385); + + template<> CONST int pi1<int> = 10; // expected-note {{previous definition is here}} + template<> CONST int pi1<int> = 10; // expected-error {{redefinition of 'pi1<int>'}} + } + + namespace before_instantiation { + template<typename T> + T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}} + + template<> int pi0<int> = 10; + template int pi0<int>; + template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} + + template<typename T1, typename T2> + CONST int pi2 = 1; + + template<typename T> CONST int pi2<T,int> = 2; + template CONST int pi2<int,int>; + } + namespace after_instantiation { + template<typename T> + T pi0 = T(3.1415926535897932385); + + template int pi0<int>; // expected-note 2{{explicit instantiation first required here}} + template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}} + template<> float pi0<int>; // expected-error {{explicit specialization of 'pi0' after instantiation}} + + template<typename T1, typename T2> + CONST int pi2 = 1; + + template CONST int pi2<int,int>; + template<typename T> CONST int pi2<T,int> = 2; + } + +#ifndef PRECXX11 + namespace auto_var { + template<typename T, typename> auto var0 = T(); + template<typename T> auto var0<T,int> = T(); + template<> auto var0<int,int> = 7; + + template<typename T, typename> auto var = T(); + template<typename T> T var<T,int> = T(5); + template<> int var<int,int> = 7; + + void foo() { + int i0 = var0<int,int>; + int b = var<int,int>; + } + } +#endif + + namespace extern_var { + // TODO: + } + + namespace diff_type { + // TODO: + template<typename T> T* var = new T(); +#ifndef PRECXX11 + template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}} + template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}} +#endif + } +} + +namespace narrowing { + template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}} +#ifndef PRECXX11 + // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\ + // expected-note@-2 {{override this message by inserting an explicit cast}} +#endif + int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}} +} + +namespace use_in_structs { + // TODO: +} + +namespace attributes { + // TODO: +} + +#ifndef PRECXX11 +namespace arrays { + template<typename T> + T* arr = new T[10]{T(10), T(23)}; + + float f = 10.5; + template<> float* arr<float> = &f; + + void bar() { + int *iarr = arr<int>; + iarr[0] = 1; + iarr[2] = 3; + iarr[6] = -2; + + float ff = *arr<float>; + float nof = arr<float>[3]; // No bounds-check in C++ + } +} +#endif + +namespace nested { + + namespace n0a { + template<typename T> + T pi0a = T(3.1415926535897932385); + } + + using namespace n0a; + int i0a = pi0a<int>; + + template float pi0a<float>; + float f0a = pi0a<float>; + + template<> double pi0a<double> = 5.2; + double d0a = pi0a<double>; + + namespace n0b { + template<typename T> + T pi0b = T(3.1415926535897932385); + } + + int i0b = n0b::pi0b<int>; + + template float n0b::pi0b<float>; + float f0b = n0b::pi0b<float>; + + template<> double n0b::pi0b<double> = 5.2; + double d0b = n0b::pi0b<double>; + + namespace n1 { + template<typename T> + T pi1a = T(3.1415926535897932385); +#ifndef PRECXX11 +// expected-note@-2 {{explicit instantiation refers here}} +#endif + + template<typename T> + T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} +#ifndef PRECXX11 +// expected-note@-2 {{explicit instantiation refers here}} +#endif + } + + namespace use_n1a { + using namespace n1; + int i1 = pi1a<int>; + + template float pi1a<float>; +#ifndef PRECXX11 +// expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}} +#endif + float f1 = pi1a<float>; + + template<> double pi1a<double> = 5.2; // expected-error {{no variable template matches specialization}} + double d1 = pi1a<double>; + } + + namespace use_n1b { + int i1 = n1::pi1b<int>; + + template float n1::pi1b<float>; +#ifndef PRECXX11 +// expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}} +#endif + float f1 = n1::pi1b<float>; + + template<> double n1::pi1b<double> = 5.2; // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \ + // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}} + double d1 = n1::pi1b<double>; + } +} + diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp index 208ea4c..b74dcb4 100644 --- a/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -1,9 +1,11 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat-pedantic -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat-pedantic -verify %s -DCXX1Y2 +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -DCXX1Y -Wc++98-compat -Werror %s -DCXX1Y2 // 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 +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-compat-pedantic -verify %s -Wno-c++98-c++11-compat-pedantic -DCXX1Y2 + // -Wc++98-compat-pedantic warns on C++11 features which we accept without a // warning in C++98 mode. @@ -30,7 +32,12 @@ void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-f 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}} +int *ArraySizeConversion = new int[ConvertToInt()]; +#ifdef CXX1Y2 +// expected-warning@-2 {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'size_t' is incompatible with C++98}} +#else +// expected-warning@-4 {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}} +#endif template<typename T> class ExternTemplate {}; extern template class ExternTemplate<int>; // expected-warning {{extern templates are incompatible with C++98}} @@ -44,8 +51,3 @@ int k = 0b1001; #ifdef CXX1Y // expected-warning@-2 {{binary integer literals are incompatible with C++ standards before C++1y}} #endif - -void f(int n) { int a[n]; } -#ifdef CXX1Y -// expected-warning@-2 {{arrays of runtime bound are incompatible with C++ standards before C++1y}} -#endif diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp index 7d36770..9690638 100644 --- a/test/SemaCXX/cxx98-compat.cpp +++ b/test/SemaCXX/cxx98-compat.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1y -Wc++98-compat -verify %s -DCXX1YCOMPAT namespace std { struct type_info; @@ -73,7 +73,7 @@ int InitList(int i = {}) { // expected-warning {{generalized initializer lists a Ctor c2 = { 3.0, 4l }; // expected-warning {{constructor call from initializer list is incompatible with C++98}} InitListCtor ilc = { true, false }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} const int &r = { 0 }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} - struct { int a; const int &r; } rr = { 0, {{0}} }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} + struct { int a; const int &r; } rr = { 0, {0} }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} } struct DelayedDefaultArgumentParseInitList { @@ -147,16 +147,12 @@ bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expression void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}} static_assert(true, "!"); // expected-warning {{static_assert declarations are incompatible with C++98}} -// FIXME: Reintroduce this test if support for inheriting constructors is -// implemented. -#if 0 struct InhCtorBase { InhCtorBase(int); }; struct InhCtorDerived : InhCtorBase { - using InhCtorBase::InhCtorBase; // xpected-warning {{inheriting constructors are incompatible with C++98}} + using InhCtorBase::InhCtorBase; // expected-warning {{inheriting constructors are incompatible with C++98}} }; -#endif struct FriendMember { static void MemberFn(); @@ -382,3 +378,79 @@ namespace rdar11736429 { X x; // expected-warning{{union member 'x' with a non-trivial constructor is incompatible with C++98}} }; } + +template<typename T> T var = T(10); +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template<typename T> T* var<T*> = new T(); +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template<> int var<int> = 10; +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template int var<int>; +float fvar = var<float>; + +class A { + template<typename T> static T var = T(10); +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + + template<typename T> static T* var<T*> = new T(); +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +}; + +struct B { template<typename T> static T v; }; +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template<typename T> T B::v = T(); +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template<typename T> T* B::v<T*> = new T(); +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template<> int B::v<int> = 10; +#ifdef CXX1YCOMPAT +// expected-warning@-2 {{variable templates are incompatible with C++ standards before C++1y}} +#else +// expected-warning@-4 {{variable templates are a C++1y extension}} +#endif + +template int B::v<int>; +float fsvar = B::v<float>; + +#ifdef CXX1YCOMPAT +int digit_seps = 123'456; // expected-warning {{digit separators are incompatible with C++ standards before C++1y}} +#endif diff --git a/test/SemaCXX/dcl_ambig_res.cpp b/test/SemaCXX/dcl_ambig_res.cpp index 97780e4..c0f1e2e 100644 --- a/test/SemaCXX/dcl_ambig_res.cpp +++ b/test/SemaCXX/dcl_ambig_res.cpp @@ -44,9 +44,7 @@ S4<int(1)> y; // expected-error{{must be a type}} void foo5() { (void)sizeof(int(1)); //expression - // FIXME: should we make this an error rather than a warning? - // (It affects SFINAE) - (void)sizeof(int()); // expected-warning{{function type}} + (void)sizeof(int()); // expected-error{{function type}} } // [dcl.ambig.res]p6: diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 87fd2da..8164b2b 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -Wno-int-to-pointer-cast -fsyntax-only -verify -pedantic-errors %s +// RUN: %clang_cc1 -Wno-int-to-pointer-cast -fsyntax-only -verify -pedantic-errors -x objective-c++ %s void f() { int a; diff --git a/test/SemaCXX/decl-init-ref.cpp b/test/SemaCXX/decl-init-ref.cpp index 4c635c1..2d0c9cb 100644 --- a/test/SemaCXX/decl-init-ref.cpp +++ b/test/SemaCXX/decl-init-ref.cpp @@ -26,4 +26,13 @@ int main() { } struct PR6139 { A (&x)[1]; }; -PR6139 x = {{A()}}; // expected-error{{non-const lvalue reference to type 'A [1]' cannot bind to a temporary of type 'A'}} +PR6139 x = {{A()}}; // expected-error{{non-const lvalue reference to type 'A [1]' cannot bind to an initializer list temporary}} + +struct PR6139b { A (&x)[1]; }; +PR6139b y = {A()}; // expected-error{{non-const lvalue reference to type 'A [1]' cannot bind to a temporary of type 'A'}} + +namespace PR16502 { + struct A { int &&temporary; int x, y; }; + int f(); + const A &c = { 10, ++c.temporary }; +} diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp index 3175af7..9f14632 100644 --- a/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -1,21 +1,24 @@ // RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -fms-extensions -verify %s +typedef void void_fun_t(); +typedef void __cdecl cdecl_fun_t(); + // Pointers to free functions -void free_func_default(); -void __cdecl free_func_cdecl(); -void __stdcall free_func_stdcall(); // expected-note {{previous declaration is here}} +void free_func_default(); // expected-note 2 {{previous declaration is here}} +void __cdecl free_func_cdecl(); // expected-note 2 {{previous declaration is here}} +void __stdcall free_func_stdcall(); // expected-note 2 {{previous declaration is here}} void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}} -void __cdecl free_func_default(); // expected-note 2 {{previous declaration is here}} +void __cdecl free_func_default(); void __stdcall free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} void __fastcall free_func_default(); // expected-error {{function declared 'fastcall' here was previously declared without calling convention}} -void free_func_cdecl(); // expected-note 2 {{previous declaration is here}} +void free_func_cdecl(); void __stdcall free_func_cdecl(); // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}} void __fastcall free_func_cdecl(); // expected-error {{function declared 'fastcall' here was previously declared 'cdecl'}} +void free_func_stdcall(); void __cdecl free_func_stdcall(); // expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}} -void free_func_stdcall(); // expected-note {{previous declaration is here}} void __fastcall free_func_stdcall(); // expected-error {{function declared 'fastcall' here was previously declared 'stdcall'}} void __cdecl free_func_fastcall(); // expected-error {{function declared 'cdecl' here was previously declared 'fastcall'}} @@ -29,6 +32,8 @@ void __cdecl free_func_default(int *); void __thiscall free_func_cdecl(char *); void __cdecl free_func_cdecl(double); +typedef void void_fun_t(); +typedef void __cdecl cdecl_fun_t(); // Pointers to member functions struct S { @@ -38,10 +43,17 @@ struct S { void __cdecl member_cdecl2(); // expected-note {{previous declaration is here}} void __thiscall member_thiscall1(); void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}} - + + // Typedefs carrying the __cdecl convention are adjusted to __thiscall. + void_fun_t member_typedef_default; // expected-note {{previous declaration is here}} + cdecl_fun_t member_typedef_cdecl1; // expected-note {{previous declaration is here}} + cdecl_fun_t __cdecl member_typedef_cdecl2; + void_fun_t __stdcall member_typedef_stdcall; + // Static member functions can't be __thiscall static void static_member_default1(); - static void static_member_default2(); // expected-note {{previous declaration is here}} + static void static_member_default2(); + static void static_member_default3(); // expected-note {{previous declaration is here}} static void __cdecl static_member_cdecl1(); static void __cdecl static_member_cdecl2(); // expected-note {{previous declaration is here}} static void __stdcall static_member_stdcall1(); @@ -58,29 +70,124 @@ struct S { void __cdecl S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} void __thiscall S::member_default2() {} +void __cdecl S::member_typedef_default() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} +void __cdecl S::member_typedef_cdecl1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} +void __cdecl S::member_typedef_cdecl2() {} +void __stdcall S::member_typedef_stdcall() {} + void S::member_cdecl1() {} void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thiscall' here was previously declared 'cdecl'}} void S::member_thiscall1() {} void __cdecl S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}} -void __cdecl S::static_member_default1() {} -void __stdcall S::static_member_default2() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} +void S::static_member_default1() {} +void __cdecl S::static_member_default2() {} +void __stdcall S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} void S::static_member_cdecl1() {} void __stdcall S::static_member_cdecl2() {} // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}} -void __cdecl S::member_variadic_default(int x, ...) { - (void)x; +void __cdecl S::member_variadic_default(int x, ...) { (void)x; } +void S::member_variadic_cdecl(int x, ...) { (void)x; } + +void __cdecl S::static_member_variadic_default(int x, ...) { (void)x; } +void S::static_member_variadic_cdecl(int x, ...) { (void)x; } + +// Declare a template using a calling convention. +template <class CharT> inline int __cdecl mystrlen(const CharT *str) { + int i; + for (i = 0; str[i]; i++) { } + return i; } -void S::member_variadic_cdecl(int x, ...) { - (void)x; +extern int sse_strlen(const char *str); +template <> inline int __cdecl mystrlen(const char *str) { + return sse_strlen(str); +} +void use_tmpl(const char *str, const int *ints) { + mystrlen(str); + mystrlen(ints); +} + +struct MixedCCStaticOverload { + static void overloaded(int a); + static void __stdcall overloaded(short a); +}; + +void MixedCCStaticOverload::overloaded(int a) {} +void MixedCCStaticOverload::overloaded(short a) {} + +// Friend function decls are cdecl by default, not thiscall. Friend method +// decls should always be redeclarations, because the class cannot be +// incomplete. +struct FriendClass { + void friend_method() {} +}; +void __stdcall friend_stdcall1() {} +class MakeFriendDecls { + int x; + friend void FriendClass::friend_method(); + friend void friend_default(); + friend void friend_stdcall1(); + friend void __stdcall friend_stdcall2(); + friend void friend_stdcall3(); // expected-note {{previous declaration is here}} +}; +void friend_default() {} +void __stdcall friend_stdcall3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}} +void __stdcall friend_stdcall2() {} + +// Test functions with multiple attributes. +void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attribute(int x); +void multi_attribute(int x) { __builtin_unreachable(); } + + +// expected-error@+2 {{stdcall and cdecl attributes are not compatible}} +// expected-error@+1 {{fastcall and cdecl attributes are not compatible}} +void __cdecl __cdecl __stdcall __cdecl __fastcall multi_cc(int x); + +template <typename T> void __stdcall StdcallTemplate(T) {} +template <> void StdcallTemplate<int>(int) {} +template <> void __stdcall StdcallTemplate<short>(short) {} + +// FIXME: Note the template, not the implicit instantiation. +// expected-error@+2 {{function declared 'cdecl' here was previously declared 'stdcall}} +// expected-note@+1 {{previous declaration is here}} +template <> void __cdecl StdcallTemplate<long>(long) {} + +struct ExactlyInt { + template <typename T> static int cast_to_int(T) { + return T::this_is_not_an_int(); + } +}; +template <> inline int ExactlyInt::cast_to_int<int>(int x) { return x; } + +namespace test2 { + class foo { + template <typename T> void bar(T v); + }; + extern template void foo::bar(const void *); } -void __cdecl S::static_member_variadic_default(int x, ...) { - (void)x; +namespace test3 { + struct foo { + typedef void bar(); + }; + bool zed(foo::bar *); + void bah() {} + void baz() { zed(bah); } } -void S::static_member_variadic_cdecl(int x, ...) { - (void)x; + +namespace test4 { + class foo { + template <typename T> static void bar(T v); + }; + extern template void foo::bar(const void *); } +namespace test5 { + template <class T> + class valarray { + void bar(); + }; + extern template void valarray<int>::bar(); +} diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp index ccde3dc..d6e85d2 100644 --- a/test/SemaCXX/decltype.cpp +++ b/test/SemaCXX/decltype.cpp @@ -37,6 +37,14 @@ struct C { // expected-error {{expected ')'}} expected-note {{to match this '('}} }; +namespace PR16529 { + struct U {}; + template <typename T> struct S { + static decltype(T{}, U{}) &f(); + }; + U &r = S<int>::f(); +} + template<typename> class conditional { }; diff --git a/test/SemaCXX/default-assignment-operator.cpp b/test/SemaCXX/default-assignment-operator.cpp index 668c600..7ef6f77 100644 --- a/test/SemaCXX/default-assignment-operator.cpp +++ b/test/SemaCXX/default-assignment-operator.cpp @@ -1,12 +1,12 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -class Base { // expected-error {{cannot define the implicit default assignment operator for 'Base', because non-static reference member 'ref' can't use default assignment operator}} \ +class Base { // expected-error {{cannot define the implicit copy assignment operator for 'Base', because non-static reference member 'ref' can't use copy assignment operator}} \ // expected-warning{{class 'Base' does not declare any constructor to initialize its non-modifiable members}} int &ref; // expected-note {{declared here}} \ // expected-note{{reference member 'ref' will never be initialized}} }; -class X : Base { // // expected-error {{cannot define the implicit default assignment operator for 'X', because non-static const member 'cint' can't use default assignment operator}} \ +class X : Base { // // expected-error {{cannot define the implicit copy assignment operator for 'X', because non-static const member 'cint' can't use copy assignment operator}} \ // expected-note{{assignment operator for 'Base' first required here}} public: X(); @@ -73,7 +73,7 @@ void i() { // Test5 -class E1 { // expected-error{{cannot define the implicit default assignment operator for 'E1', because non-static const member 'a' can't use default assignment operator}} +class E1 { // expected-error{{cannot define the implicit copy assignment operator for 'E1', because non-static const member 'a' can't use copy assignment operator}} public: const int a; // expected-note{{declared here}} @@ -101,7 +101,7 @@ namespace ProtectedCheck { X x; }; - void f(Z z) { z = z; } // expected-note{{implicit default copy assignment operator}} + void f(Z z) { z = z; } // expected-note{{implicit copy assignment operator}} } diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp index c8c197e..b661776 100644 --- a/test/SemaCXX/default1.cpp +++ b/test/SemaCXX/default1.cpp @@ -21,7 +21,7 @@ struct X { X(int); }; -void j(X x = 17); +void j(X x = 17); // expected-note{{'::j' declared here}} struct Y { // expected-note 2{{candidate}} explicit Y(int); @@ -46,8 +46,13 @@ int l () { 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, single argument 'f' was not specified}} + void j (int f); + j(); // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::j'?}} + } + void jj (int f = 4); + { + void jj (int f); // expected-note{{'jj' declared here}} + jj(); // expected-error{{too few arguments to function call, single argument 'f' was not specified}} } } diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp new file mode 100644 index 0000000..0335a80 --- /dev/null +++ b/test/SemaCXX/deprecated.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++98 %s -Wdeprecated -verify -triple x86_64-linux-gnu +// RUN: %clang_cc1 -std=c++11 %s -Wdeprecated -verify -triple x86_64-linux-gnu +// RUN: %clang_cc1 -std=c++1y %s -Wdeprecated -verify -triple x86_64-linux-gnu + +// RUN: %clang_cc1 -std=c++1y %s -Wdeprecated -verify -triple x86_64-linux-gnu -Wno-deprecated-register -DNO_DEPRECATED_FLAGS + +#include "Inputs/register.h" + +void f() throw(); +void g() throw(int); +void h() throw(...); +#if __cplusplus >= 201103L +// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept' instead}} +// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}} +// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}} +#endif + +void stuff() { + register int n; +#if __cplusplus >= 201103L && !defined(NO_DEPRECATED_FLAGS) + // expected-warning@-2 {{'register' storage class specifier is deprecated}} +#endif + + register int m asm("rbx"); // no-warning + + int k = to_int(n); // no-warning + + bool b; + ++b; // expected-warning {{incrementing expression of type bool is deprecated}} + + // FIXME: This is ill-formed in C++11. + char *p = "foo"; // expected-warning {{conversion from string literal to 'char *' is deprecated}} +} + +struct S { int n; }; +struct T : private S { + S::n; +#if __cplusplus < 201103L + // expected-warning@-2 {{access declarations are deprecated; use using declarations instead}} +#else + // expected-error@-4 {{ISO C++11 does not allow access declarations; use using declarations instead}} +#endif +}; + +#if __cplusplus >= 201103L +namespace DeprecatedCopy { + struct Assign { + Assign &operator=(const Assign&); // expected-warning {{definition of implicit copy constructor for 'Assign' is deprecated because it has a user-declared copy assignment operator}} + }; + Assign a1, a2(a1); // expected-note {{implicit copy constructor for 'Assign' first required here}} + + struct Ctor { + Ctor(); + Ctor(const Ctor&); // expected-warning {{definition of implicit copy assignment operator for 'Ctor' is deprecated because it has a user-declared copy constructor}} + }; + Ctor b1, b2; + void f() { b1 = b2; } // expected-note {{implicit copy assignment operator for 'Ctor' first required here}} + + struct Dtor { + ~Dtor(); + // expected-warning@-1 {{definition of implicit copy constructor for 'Dtor' is deprecated because it has a user-declared destructor}} + // expected-warning@-2 {{definition of implicit copy assignment operator for 'Dtor' is deprecated because it has a user-declared destructor}} + }; + Dtor c1, c2(c1); // expected-note {{implicit copy constructor for 'Dtor' first required here}} + void g() { c1 = c2; } // expected-note {{implicit copy assignment operator for 'Dtor' first required here}} +} +#endif diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index f3c6ab0..e511be0 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -363,3 +363,7 @@ namespace PR7900 { (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}} } } + +namespace PR16892 { + auto p = &A::~A; // expected-error{{taking the address of a destructor}} +} diff --git a/test/SemaCXX/dynamic-cast.cpp b/test/SemaCXX/dynamic-cast.cpp index b73e8c5..b605194 100644 --- a/test/SemaCXX/dynamic-cast.cpp +++ b/test/SemaCXX/dynamic-cast.cpp @@ -37,6 +37,8 @@ void basic_bad() (void)dynamic_cast<Incomplete*>((A*)0); // expected-error {{'Incomplete' is an incomplete type}} // incomplete -> ptr (void)dynamic_cast<A*>((Incomplete*)0); // expected-error {{'Incomplete' is an incomplete type}} + // rvalue -> lvalue + (void)dynamic_cast<A&>(A()); // expected-error {{dynamic_cast from rvalue to reference type 'A &'}} } void same() diff --git a/test/SemaCXX/enum-increment.cpp b/test/SemaCXX/enum-increment.cpp new file mode 100644 index 0000000..dc1a921 --- /dev/null +++ b/test/SemaCXX/enum-increment.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify + +enum A { A1, A2, A3 }; +void test() { + A a; + a++; // expected-error{{cannot increment expression of enum type 'A'}} + a--; // expected-error{{cannot decrement expression of enum type 'A'}} + ++a; // expected-error{{cannot increment expression of enum type 'A'}} + --a; // expected-error{{cannot decrement expression of enum type 'A'}} +} + +enum B {B1, B2}; +inline B &operator++ (B &b) { b = B((int)b+1); return b; } +inline B operator++ (B &b, int) { B ret = b; ++b; return b; } + +void foo(enum B b) { ++b; b++; } diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index d01000d..b4aad18b 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -266,3 +266,33 @@ namespace PR15633 { struct B { enum class E; }; template<typename T> enum class B::E { e }; // expected-error {{enumeration cannot be a template}} } + +namespace PR16900 { + enum class A; + A f(A a) { return -a; } // expected-error {{invalid argument type 'PR16900::A' to unary expression}} +} + +namespace rdar15124329 { + enum class B : bool { F, T }; + + const rdar15124329::B T1 = B::T; + typedef B C; const C T2 = B::T; + + static_assert(T1 != B::F, ""); + static_assert(T2 == B::T, ""); +} + +namespace PR18044 { + enum class E { a }; + + int E::e = 0; // expected-error {{does not refer into a class}} + void E::f() {} // expected-error {{does not refer into a class}} + struct E::S {}; // expected-error {{no struct named 'S'}} + struct T : E::S {}; // expected-error {{expected class name}} + enum E::E {}; // expected-error {{no enum named 'E'}} + int E::*p; // expected-error {{does not point into a class}} + using E::f; // expected-error {{no member named 'f'}} + + using E::a; // ok! + E b = a; +} diff --git a/test/SemaCXX/enum-unscoped-nonexistent.cpp b/test/SemaCXX/enum-unscoped-nonexistent.cpp index e9da38f..7da9a96 100644 --- a/test/SemaCXX/enum-unscoped-nonexistent.cpp +++ b/test/SemaCXX/enum-unscoped-nonexistent.cpp @@ -6,7 +6,7 @@ struct Base { template<typename T> struct S : Base { enum E : int; constexpr int f() const; - constexpr int g() const; // expected-note {{declared here}} + constexpr int g() const; void h(); }; template<> enum S<char>::E : int {}; // expected-note {{enum 'S<char>::E' was explicitly specialized here}} @@ -23,7 +23,7 @@ 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() const { 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<char>().g() == 1, ""); // expected-note {{here}} expected-error {{not an integral constant expression}} static_assert(S<short>().g() == 2, ""); static_assert(S<long>().g() == 8, ""); diff --git a/test/SemaCXX/err_init_conversion_failed.cpp b/test/SemaCXX/err_init_conversion_failed.cpp new file mode 100644 index 0000000..0652e7a --- /dev/null +++ b/test/SemaCXX/err_init_conversion_failed.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void test0() { + char variable = (void)0; + // expected-error@-1{{cannot initialize a variable}} +} + +void test1(int x = (void)0) {} + // expected-error@-1{{cannot initialize a parameter}} + // expected-note@-2{{here}} + +int test2() { + return (void)0; + // expected-error@-1{{cannot initialize return object}} +} + +struct S4 { + S4() : x((void)0) {}; + // expected-error@-1{{cannot initialize a member subobject}} + int x; +}; + +void test5() { + int foo[2] = {1, (void)0}; + // expected-error@-1{{cannot initialize an array element}} +} + +void test6() { + new int((void)0); + // expected-error@-1{{cannot initialize a new value}} +} + +typedef short short2 __attribute__ ((__vector_size__ (2))); +void test10() { + short2 V = { (void)0 }; + // expected-error@-1{{cannot initialize a vector element}} +} + +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float4 __attribute__((ext_vector_type(4))); + +void test14(const float2 in, const float2 out) { + const float4 V = (float4){ in, out }; + // expected-error@-1{{cannot initialize a compound literal initializer}} +} diff --git a/test/SemaCXX/explicit.cpp b/test/SemaCXX/explicit.cpp index 5ce2cf1..1c4d770 100644 --- a/test/SemaCXX/explicit.cpp +++ b/test/SemaCXX/explicit.cpp @@ -4,11 +4,11 @@ struct A { A(int); }; -struct B { +struct B { // expected-note+ {{candidate}} explicit B(int); }; -B::B(int) { } +B::B(int) { } // expected-note+ {{here}} struct C { void f(const A&); @@ -18,6 +18,22 @@ struct C { void f(C c) { c.f(10); } + +A a0 = 0; +A a1(0); +A &&a2 = 0; +A &&a3(0); +A a4{0}; +A &&a5 = {0}; +A &&a6{0}; + +B b0 = 0; // expected-error {{no viable conversion}} +B b1(0); +B &&b2 = 0; // expected-error {{could not bind}} +B &&b3(0); // expected-error {{could not bind}} +B b4{0}; +B &&b5 = {0}; // expected-error {{chosen constructor is explicit}} +B &&b6{0}; } namespace Conversion { @@ -40,12 +56,11 @@ namespace Conversion { void testExplicit() { // Taken from 12.3.2p2 - class Y { }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Z' to 'const Y &' for 1st argument}} \ - expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Z' to 'Y &&' for 1st argument}} \ - expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Z' to 'const Y &' for 1st argument}} \ - expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Z' to 'Y &&' for 1st argument}} + class X { X(); }; // expected-note+ {{candidate constructor}} + class Y { }; // expected-note+ {{candidate constructor (the implicit}} struct Z { + explicit operator X() const; explicit operator Y() const; explicit operator int() const; }; @@ -53,6 +68,7 @@ namespace Conversion { Z z; // 13.3.1.4p1 & 8.5p16: Y y2 = z; // expected-error {{no viable conversion from 'Z' to 'Y'}} + Y y2b(z); Y y3 = (Y)z; Y y4 = Y(z); Y y5 = static_cast<Y>(z); @@ -63,7 +79,24 @@ namespace Conversion { int i4(z); // 13.3.1.6p1 & 8.5.3p5: const Y& y6 = z; // expected-error {{no viable conversion from 'Z' to 'const Y'}} - const int& y7(z); + const int& y7 = z; // expected-error {{no viable conversion from 'Z' to 'const int'}} + const Y& y8(z); + const int& y9(z); + + // Y is an aggregate, so aggregate-initialization is performed and the + // conversion function is not considered. + const Y y10{z}; // expected-error {{excess elements}} + const Y& y11{z}; // expected-error {{no viable conversion from 'Z' to 'const Y'}} + const int& y12{z}; + + // X is not an aggregate, so constructors are considered. + // However, by 13.3.3.1/4, only standard conversion sequences and + // ellipsis conversion sequences are considered here, so this is not + // allowed. + // FIXME: It's not really clear that this is a sensible restriction for this + // case. g++ allows this, EDG does not. + const X x1{z}; // expected-error {{no matching constructor}} + const X& x2{z}; // expected-error {{no matching constructor}} } void testBool() { @@ -119,6 +152,40 @@ namespace Conversion { // 6.5.3: for (;b;) {} for (;n;) {} + + // 13.3.1.5p1: + bool direct1(b); + bool direct2(n); + int direct3(b); + int direct4(n); // expected-error {{no viable conversion}} + const bool &direct5(b); + const bool &direct6(n); + const int &direct7(b); + const int &direct8(n); // expected-error {{no viable conversion}} + bool directList1{b}; + bool directList2{n}; + int directList3{b}; + int directList4{n}; // expected-error {{no viable conversion}} + const bool &directList5{b}; + const bool &directList6{n}; + const int &directList7{b}; + const int &directList8{n}; // expected-error {{no viable conversion}} + bool copy1 = b; + bool copy2 = n; // expected-error {{no viable conversion}} + int copy3 = b; + int copy4 = n; // expected-error {{no viable conversion}} + const bool ©5 = b; + const bool ©6 = n; // expected-error {{no viable conversion}} + const int ©7 = b; + const int ©8 = n; // expected-error {{no viable conversion}} + bool copyList1 = {b}; + bool copyList2 = {n}; // expected-error {{no viable conversion}} + int copyList3 = {b}; + int copyList4 = {n}; // expected-error {{no viable conversion}} + const bool ©List5 = {b}; + const bool ©List6 = {n}; // expected-error {{no viable conversion}} + const int ©List7 = {b}; + const int ©List8 = {n}; // expected-error {{no viable conversion}} } void testNew() @@ -145,14 +212,14 @@ namespace Conversion { operator int*(); }; struct NotPtr { - explicit operator int*(); + explicit operator int*(); // expected-note {{conversion}} }; Ptr p; NotPtr np; delete p; - delete np; // expected-error {{cannot delete expression of type 'NotPtr'}} + delete np; // expected-error {{converting delete expression from type 'NotPtr' to type 'int *' invokes an explicit conversion function}} } void testFunctionPointer() @@ -173,3 +240,9 @@ namespace Conversion { nfp(1); // expected-error {{type 'NotFP' does not provide a call operator}} } } + +namespace pr8264 { + struct Test { + explicit explicit Test(int x); // expected-warning{{duplicate 'explicit' declaration specifier}} + }; +} diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 2767d4a..3a00687 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -189,12 +189,12 @@ struct Class : BaseClass static int& NestedFuncTemplate() { return variable; } // expected-note{{possible target for call}} template <class T> - int& NestedMemfunTemplate() { return variable; } + int& NestedMemfunTemplate() { return variable; } // expected-note{{possible target for call}} int operator*() const; template <class T> - int operator+(T) const; + int operator+(T) const; // expected-note{{possible target for call}} int NonstaticMemberFunction(); static int StaticMemberFunction(); diff --git a/test/SemaCXX/extern-c.cpp b/test/SemaCXX/extern-c.cpp index c55b10d..dfbf386 100644 --- a/test/SemaCXX/extern-c.cpp +++ b/test/SemaCXX/extern-c.cpp @@ -2,25 +2,25 @@ namespace test1 { extern "C" { - void f() { - void test1_g(int); // expected-note {{previous declaration is here}} + void test1_f() { + void test1_g(int); } } } -int test1_g(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} +int test1_g(int); namespace test2 { extern "C" { - void f() { - extern int test2_x; // expected-note {{previous definition is here}} + void test2_f() { + extern int test2_x; // expected-note {{declared with C language linkage here}} } } } -float test2_x; // expected-error {{redefinition of 'test2_x' with a different type: 'float' vs 'int'}} +float test2_x; // expected-error {{declaration of 'test2_x' in global scope conflicts with declaration with C language linkage}} namespace test3 { extern "C" { - void f() { + void test3_f() { extern int test3_b; // expected-note {{previous definition is here}} } } @@ -29,20 +29,40 @@ namespace test3 { } } +namespace N { + extern "C" { + void test4_f() { + extern int test4_b; // expected-note {{declared with C language linkage here}} + } + } +} +static float test4_b; // expected-error {{declaration of 'test4_b' in global scope conflicts with declaration with C language linkage}} + extern "C" { - void test4_f() { - extern int test4_b; // expected-note {{previous definition is here}} + void test4c_f() { + extern int test4_c; // expected-note {{previous}} + } +} +static float test4_c; // expected-error {{redefinition of 'test4_c' with a different type: 'float' vs 'int'}} + +namespace N { + extern "C" { + void test5_f() { + extern int test5_b; // expected-note {{declared with C language linkage here}} + } } } -static float test4_b; // expected-error {{redefinition of 'test4_b' with a different type: 'float' vs 'int'}} +extern "C" { + static float test5_b; // expected-error {{declaration of 'test5_b' in global scope conflicts with declaration with C language linkage}} +} extern "C" { - void test5_f() { - extern int test5_b; // expected-note {{previous definition is here}} + void test5c_f() { + extern int test5_c; // expected-note {{previous}} } } extern "C" { - static float test5_b; // expected-error {{redefinition of 'test5_b' with a different type: 'float' vs 'int'}} + static float test5_c; // expected-error {{redefinition of 'test5_c' with a different type: 'float' vs 'int'}} } extern "C" { @@ -56,3 +76,131 @@ namespace foo { extern float test6_b; } } + +namespace linkage { + namespace redecl { + extern "C" { + static void linkage_redecl(); + static void linkage_redecl(int); + void linkage_redecl(); // ok, still not extern "C" + void linkage_redecl(int); // ok, still not extern "C" + void linkage_redecl(float); // expected-note {{previous}} + void linkage_redecl(double); // expected-error {{conflicting types}} + } + } + namespace from_outer { + void linkage_from_outer_1(); // expected-note {{previous}} + void linkage_from_outer_2(); // expected-note {{previous}} + extern "C" { + void linkage_from_outer_1(int); + void linkage_from_outer_1(); // expected-error {{different language linkage}} + void linkage_from_outer_2(); // expected-error {{different language linkage}} + } + } + namespace mixed { + extern "C" { + void linkage_mixed_1(); + static void linkage_mixed_1(int); + + static void linkage_mixed_2(int); + void linkage_mixed_2(); + } + } + namespace across_scopes { + namespace X { + extern "C" void linkage_across_scopes_f() { + void linkage_across_scopes_g(); // expected-note {{previous}} + } + } + namespace Y { + extern "C" void linkage_across_scopes_g(int); // expected-error {{conflicting}} + } + } +} + +int lookup_in_global_f; // expected-note {{here}} +namespace lookup_in_global { + void lookup_in_global_f(); + void lookup_in_global_g(); + extern "C" { + void lookup_in_global_f(int); // expected-error {{conflicts with declaration in global scope}} + void lookup_in_global_g(int); // expected-note {{here}} + } +} +int lookup_in_global_g; // expected-error {{conflicts with declaration with C language linkage}} + +namespace N1 { + extern "C" int different_kind_1; // expected-note {{here}} + extern "C" void different_kind_2(); // expected-note {{here}} +} +namespace N2 { + extern "C" void different_kind_1(); // expected-error {{different kind of symbol}} + extern "C" int different_kind_2; // expected-error {{different kind of symbol}} +} + +// We allow all these even though the standard says they are ill-formed. +extern "C" { + struct stat {}; // expected-warning{{empty struct has size 0 in C, size 1 in C++}} + void stat(struct stat); +} +namespace X { + extern "C" { + void stat(struct ::stat); + } +} +int stat(int *p); +void global_fn_vs_extern_c_var_1(); +namespace X { + extern "C" int global_fn_vs_extern_c_var_1; + extern "C" int global_fn_vs_extern_c_var_2; +} +void global_fn_vs_extern_c_var_2(); +void global_fn_vs_extern_c_fn_1(); +namespace X { + extern "C" int global_fn_vs_extern_c_fn_1(int); + extern "C" int global_fn_vs_extern_c_fn_2(int); +} +void global_fn_vs_extern_c_fn_2(); +extern "C" void name_with_using_decl_1(int); +namespace using_decl { + void name_with_using_decl_1(); + void name_with_using_decl_2(); + void name_with_using_decl_3(); +} +using using_decl::name_with_using_decl_1; +using using_decl::name_with_using_decl_2; +extern "C" void name_with_using_decl_2(int); +extern "C" void name_with_using_decl_3(int); +using using_decl::name_with_using_decl_3; + +// We do not allow a global variable and an extern "C" function to have the same +// name, because such entities may have the same mangled name. +int global_var_vs_extern_c_fn_1; // expected-note {{here}} +namespace X { + extern "C" void global_var_vs_extern_c_fn_1(); // expected-error {{conflicts with declaration in global scope}} + extern "C" void global_var_vs_extern_c_fn_2(); // expected-note {{here}} +} +int global_var_vs_extern_c_fn_2; // expected-error {{conflicts with declaration with C language linkage}} +int global_var_vs_extern_c_var_1; // expected-note {{here}} +namespace X { + extern "C" double global_var_vs_extern_c_var_1; // expected-error {{conflicts with declaration in global scope}} + extern "C" double global_var_vs_extern_c_var_2; // expected-note {{here}} +} +int global_var_vs_extern_c_var_2; // expected-error {{conflicts with declaration with C language linkage}} + +template <class T> struct pr5065_n1 {}; +extern "C" { + union pr5065_1 {}; // expected-warning{{empty union has size 0 in C, size 1 in C++}} + struct pr5065_2 { int: 0; }; // expected-warning{{struct has size 0 in C, size 1 in C++}} + struct pr5065_3 {}; // expected-warning{{empty struct has size 0 in C, size 1 in C++}} + struct pr5065_4 { // expected-warning{{empty struct has size 0 in C, size 1 in C++}} + struct Inner {}; // expected-warning{{empty struct has size 0 in C, size 1 in C++}} + }; + // These should not warn + class pr5065_n3 {}; + pr5065_n1<int> pr5065_v; + struct pr5065_n4 { void m() {} }; + struct pr5065_n5 : public pr5065_3 {}; + struct pr5065_n6 : public virtual pr5065_3 {}; +} +struct pr5065_n7 {}; diff --git a/test/SemaCXX/flexible-array-test.cpp b/test/SemaCXX/flexible-array-test.cpp index e6c3132..f287711 100644 --- a/test/SemaCXX/flexible-array-test.cpp +++ b/test/SemaCXX/flexible-array-test.cpp @@ -66,4 +66,8 @@ struct Storage : StorageBase { int data[]; }; +struct VirtStorage : virtual StorageBase { + int data[]; // expected-error {{flexible array member 'data' not allowed in struct which has a virtual base class}} +}; + } diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index 953c98b..b3cf9c3 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 namespace value_range_detail { template<typename T> @@ -180,3 +180,32 @@ namespace test4 { for (y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} } } + +namespace test5 { + // Test error-recovery. + void f() { + for (auto x : undeclared_identifier) // expected-error {{undeclared identifier}} + for (auto y : x->foo) + y->bar(); + for (auto x : 123) // expected-error {{no viable 'begin'}} + x->foo(); + } +} + +namespace test6 { + void foo(int arr[]) { // expected-note {{declared here}} + for (auto i : arr) { } + // expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'int []' is treated as pointer type 'int *'}} + } + + struct vector { + int *begin() { return 0; } + int *end() { return 0; } + }; + + void foo(vector arr[]) { // expected-note {{declared here}} + // Don't suggest to dereference arr. + for (auto i : arr) { } + // expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'test6::vector []' is treated as pointer type 'test6::vector *'}} + } +} diff --git a/test/SemaCXX/format-strings-0x.cpp b/test/SemaCXX/format-strings-0x.cpp index 7b3aef1..7e41c7f 100644 --- a/test/SemaCXX/format-strings-0x.cpp +++ b/test/SemaCXX/format-strings-0x.cpp @@ -24,4 +24,8 @@ void f(char **sp, float *fp) { \u1234\U0010fffe %d)foo" // expected-warning {{more '%' conversions than data arguments}} ); + + printf("init list: %d", { 0 }); // expected-error {{cannot pass initializer list to variadic function; expected type from format string was 'int'}} + printf("void: %d", f(sp, fp)); // expected-error {{cannot pass expression of type 'void' to variadic function; expected type from format string was 'int'}} + printf(0, { 0 }); // expected-error {{cannot pass initializer list to variadic function}} } diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp index b401a06..aed2ab2 100644 --- a/test/SemaCXX/friend.cpp +++ b/test/SemaCXX/friend.cpp @@ -44,7 +44,7 @@ namespace test2 { // PR5134 namespace test3 { class Foo { - friend const int getInt(int inInt = 0); + friend const int getInt(int inInt = 0) {} }; } @@ -134,7 +134,7 @@ namespace test6_3 { namespace test7 { extern "C" { class X { - friend int f() { return 42; } + friend int test7_f() { return 42; } }; } } @@ -154,3 +154,137 @@ namespace test8 { friend void B::f(); // expected-error {{cannot befriend target of using declaration}} }; } + +// PR16423 +namespace test9 { + class C { + }; + struct A { + friend void C::f(int, int, int) {} // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}} + }; +} + +namespace test10 { + struct X {}; + extern void f10_a(); + extern void f10_a(X); + struct A { + friend void f10_a(); + friend void f10_b(); + friend void f10_c(); + friend void f10_d(); + friend void f10_a(X); + friend void f10_b(X); + friend void f10_c(X); + friend void f10_d(X); + }; + extern void f10_b(); + extern void f10_b(X); + struct B { + friend void f10_a(); + friend void f10_b(); + friend void f10_c(); + friend void f10_d(); + friend void f10_a(X); + friend void f10_b(X); + friend void f10_c(X); + friend void f10_d(X); + }; + extern void f10_c(); + extern void f10_c(X); + + // FIXME: Give a better diagnostic for the case where a function exists but is + // not visible. + void g(X x) { + f10_a(); + f10_b(); + f10_c(); + f10_d(); // expected-error {{undeclared identifier}} + + ::test10::f10_a(); + ::test10::f10_b(); + ::test10::f10_c(); + ::test10::f10_d(); // expected-error {{no member named 'f10_d'}} + + f10_a(x); + f10_b(x); + f10_c(x); + f10_d(x); // PR16597: expected-error {{undeclared identifier}} + + ::test10::f10_a(x); + ::test10::f10_b(x); + ::test10::f10_c(x); + ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}} + } + + struct Y : X { + friend void f10_d(); + friend void f10_d(X); + }; + + struct Z { + operator X(); + friend void f10_d(); + friend void f10_d(X); + }; + + void g(X x, Y y, Z z) { + f10_d(); // expected-error {{undeclared identifier}} + ::test10::f10_d(); // expected-error {{no member named 'f10_d'}} + + // f10_d is visible to ADL in the second and third cases. + f10_d(x); // expected-error {{undeclared identifier}} + f10_d(y); + f10_d(z); + + // No ADL here. + ::test10::f10_d(x); // expected-error {{no type named 'f10_d'}} + ::test10::f10_d(y); // expected-error {{no type named 'f10_d'}} + ::test10::f10_d(z); // expected-error {{no type named 'f10_d'}} + } + + void local_externs(X x, Y y) { + extern void f10_d(); + extern void f10_d(X); + f10_d(); + f10_d(x); + // FIXME: This lookup should fail, because the local extern declaration + // should suppress ADL. + f10_d(y); + { + int f10_d; + f10_d(); // expected-error {{not a function}} + f10_d(x); // expected-error {{not a function}} + f10_d(y); // expected-error {{not a function}} + } + } + + void i(X x, Y y) { + f10_d(); // expected-error {{undeclared identifier}} + f10_d(x); // expected-error {{undeclared identifier}} + f10_d(y); + } + + struct C { + friend void f10_d(); + friend void f10_d(X); + }; + + void j(X x, Y y) { + f10_d(); // expected-error {{undeclared identifier}} + f10_d(x); // expected-error {{undeclared identifier}} + f10_d(y); + } + + extern void f10_d(); + extern void f10_d(X); + void k(X x, Y y, Z z) { + // All OK now. + f10_d(); + f10_d(x); + ::test10::f10_d(); + ::test10::f10_d(x); + ::test10::f10_d(y); + ::test10::f10_d(z); + } +} diff --git a/test/SemaCXX/function-pointer-arguments.cpp b/test/SemaCXX/function-pointer-arguments.cpp new file mode 100644 index 0000000..9f3fb0a --- /dev/null +++ b/test/SemaCXX/function-pointer-arguments.cpp @@ -0,0 +1,52 @@ +//RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR16570 { + int f1(int, int); + int f2(const int, int); + int f3(int&, int); + int f4(const int&, int); + + void good() { + int(*g1)(int, int) = f1; + int(*g2)(const int, int) = f1; + int(*g3)(volatile int, int) = f1; + int(*g4)(int, int) = f2; + int(*g5)(const int, int) = f2; + int(*g6)(volatile int, int) = f2; + int(*g7)(int&, int) = f3; + int(*g8)(const int&, int) = f4; + } + + void bad() { + void (*g1)(int, int) = f1; + // expected-error@-1 {{different return type ('void' vs 'int'}} + const int (*g2)(int, int) = f1; + // expected-error@-1 {{different return type ('const int' vs 'int')}} + + int (*g3)(char, int) = f1; + // expected-error@-1 {{type mismatch at 1st parameter ('char' vs 'int')}} + int (*g4)(int, char) = f1; + // expected-error@-1 {{type mismatch at 2nd parameter ('char' vs 'int')}} + + int (*g5)(int) = f1; + // expected-error@-1 {{different number of parameters (1 vs 2)}} + + int (*g6)(int, int, int) = f1; + // expected-error@-1 {{different number of parameters (3 vs 2)}} + + int (*g7)(const int, char) = f1; + // expected-error@-1 {{type mismatch at 2nd parameter ('char' vs 'int')}} + int (*g8)(int, char) = f2; + // expected-error@-1 {{type mismatch at 2nd parameter ('char' vs 'int')}} + int (*g9)(const int&, char) = f3; + // expected-error@-1 {{type mismatch at 1st parameter ('const int &' vs 'int &')}} + int (*g10)(int&, char) = f4; + // expected-error@-1 {{type mismatch at 1st parameter ('int &' vs 'const int &')}} + } + + typedef void (*F)(const char * __restrict__, int); + void g(const char *, unsigned); + F f = g; + // expected-error@-1 {{type mismatch at 2nd parameter ('int' vs 'unsigned int')}} + +} diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp index b9d1f23..2bc0d90 100644 --- a/test/SemaCXX/function-redecl.cpp +++ b/test/SemaCXX/function-redecl.cpp @@ -4,22 +4,24 @@ int foo(int); namespace N { void f1() { void foo(int); // okay + void bar(int); // expected-note 2{{previous declaration is here}} } - // FIXME: we shouldn't even need this declaration to detect errors - // below. - void foo(int); // expected-note{{previous declaration is here}} + void foo(int); // expected-note 2{{previous declaration is here}} void f2() { - int foo(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} + int foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + int bar(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + int baz(int); // expected-note {{previous declaration is here}} { int foo; + int bar; + int baz; { - // FIXME: should diagnose this because it's incompatible with - // N::foo. However, name lookup isn't properly "skipping" the - // "int foo" above. - float foo(int); + float foo(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + float bar(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} + float baz(int); // expected-error {{functions that differ only in their return type cannot be overloaded}} } } } diff --git a/test/SemaCXX/function-type-qual.cpp b/test/SemaCXX/function-type-qual.cpp index ccb5747..613ac9b 100644 --- a/test/SemaCXX/function-type-qual.cpp +++ b/test/SemaCXX/function-type-qual.cpp @@ -29,3 +29,11 @@ cfn C::*mpg; // Don't crash! void (PR14171)() const; // expected-error {{non-member function cannot have 'const' qualifier}} + +// Test template instantiation of decayed array types. Not really related to +// type quals. +template <typename T> void arrayDecay(const T a[]) { } +void instantiateArrayDecay() { + int a[1]; + arrayDecay(a); +} diff --git a/test/SemaCXX/gnu-flags.cpp b/test/SemaCXX/gnu-flags.cpp new file mode 100644 index 0000000..05770c5 --- /dev/null +++ b/test/SemaCXX/gnu-flags.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu +// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu +// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \ +// RUN: -Wgnu-anonymous-struct -Wredeclared-class-member \ +// RUN: -Wgnu-flexible-array-union-member -Wgnu-folding-constant \ +// RUN: -Wgnu-empty-struct +// RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wgnu \ +// RUN: -Wno-gnu-anonymous-struct -Wno-redeclared-class-member \ +// RUN: -Wno-gnu-flexible-array-union-member -Wno-gnu-folding-constant \ +// RUN: -Wno-gnu-empty-struct +// Additional disabled tests: +// %clang_cc1 -fsyntax-only -verify %s -DANONYMOUSSTRUCT -Wno-gnu -Wgnu-anonymous-struct +// %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDCLASSMEMBER -Wno-gnu -Wredeclared-class-member +// %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYUNIONMEMBER -Wno-gnu -Wgnu-flexible-array-union-member +// %clang_cc1 -fsyntax-only -verify %s -DFOLDINGCONSTANT -Wno-gnu -Wgnu-folding-constant +// %clang_cc1 -fsyntax-only -verify %s -DEMPTYSTRUCT -Wno-gnu -Wgnu-empty-struct + +#if NONE +// expected-no-diagnostics +#endif + + +#if ALL || ANONYMOUSSTRUCT +// expected-warning@+5 {{anonymous structs are a GNU extension}} +#endif + +struct as { + int x; + struct { + int a; + float b; + }; +}; + + +#if ALL || REDECLAREDCLASSMEMBER +// expected-note@+6 {{previous declaration is here}} +// expected-warning@+6 {{class member cannot be redeclared}} +#endif + +namespace rcm { + class A { + class X; + class X; + class X {}; + }; +} + + +#if ALL || FLEXIBLEARRAYUNIONMEMBER +// expected-warning@+6 {{flexible array member 'c1' in a union is a GNU extension}} +#endif + +struct faum { + int l; + union { + int c1[]; + }; +}; + + +#if ALL || FOLDINGCONSTANT +// expected-warning@+4 {{in-class initializer for static data member is not a constant expression; folding it to a constant is a GNU extension}} +#endif + +struct fic { + static const int B = int(0.75 * 1000 * 1000); +}; + + +#if ALL || EMPTYSTRUCT +// expected-warning@+3 {{flexible array member 'a' in otherwise empty struct is a GNU extension}} +#endif + +struct ofam {int a[];}; + diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index c80323c..39c6b1f 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -16,7 +16,7 @@ void f() { } int a() { - const int t=t; // expected-note {{declared here}} + const int t=t; // expected-note {{declared here}} expected-note {{read of object outside its lifetime}} switch(1) { // expected-warning {{no case matching constant switch condition '1'}} case t:; // expected-error {{not an integral constant expression}} expected-note {{initializer of 't' is not a constant expression}} } diff --git a/test/SemaCXX/implicit-virtual-member-functions.cpp b/test/SemaCXX/implicit-virtual-member-functions.cpp index f6082e5..cd547f5 100644 --- a/test/SemaCXX/implicit-virtual-member-functions.cpp +++ b/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -9,7 +9,7 @@ struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} void operator delete (void *, int); // expected-note {{'operator delete' declared here}} }; -void B::f() { // expected-note {{implicit default destructor for 'B' first required here}} +void B::f() { // expected-note {{implicit destructor for 'B' first required here}} } struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} @@ -17,13 +17,13 @@ struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} }; -C::C() { } // expected-note {{implicit default destructor for 'C' first required here}} +C::C() { } // expected-note {{implicit destructor for 'C' first required here}} struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} }; void f() { - new D; // expected-note {{implicit default destructor for 'D' first required here}} + new D; // expected-note {{implicit destructor for 'D' first required here}} } diff --git a/test/SemaCXX/inherit.cpp b/test/SemaCXX/inherit.cpp index a926c81..abeed9a 100644 --- a/test/SemaCXX/inherit.cpp +++ b/test/SemaCXX/inherit.cpp @@ -30,3 +30,6 @@ typedef G_copy G_copy_3; class H : G_copy, A, G_copy_2, // expected-error{{base class 'G_copy' (aka 'G') specified more than once as a direct base class}} public G_copy_3 { }; // expected-error{{base class 'G_copy' (aka 'G') specified more than once as a direct base class}} + +struct J { char c; int i[]; }; +struct K : J { }; // expected-error{{base class 'J' has a flexible array member}} diff --git a/test/SemaCXX/init-priority-attr.cpp b/test/SemaCXX/init-priority-attr.cpp index 6facebf..a91eb60 100644 --- a/test/SemaCXX/init-priority-attr.cpp +++ b/test/SemaCXX/init-priority-attr.cpp @@ -19,11 +19,11 @@ extern Two koo[]; Two foo __attribute__((init_priority(101))) ( 5, 6 ); -Two goo __attribute__((init_priority(2,3))) ( 5, 6 ); // expected-error {{attribute takes one argument}} +Two goo __attribute__((init_priority(2,3))) ( 5, 6 ); // expected-error {{'init_priority' attribute takes one argument}} Two coo[2] __attribute__((init_priority(3))); // expected-error {{init_priority attribute requires integer constant between 101 and 65535 inclusive}} -Two koo[4] __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires integer constant}} +Two koo[4] __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires an integer constant}} Two func() __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index a333f38..e290424 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s +// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify -fblocks %s +// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fblocks %s namespace std { class type_info; }; @@ -109,27 +110,30 @@ namespace PR12031 { } } -namespace NullPtr { +namespace Array { int &f(int *p); char &f(...); void g() { - int n = 0; + int n = -1; [=] { - char &k = f(n); // not a null pointer constant + int arr[n]; // VLA } (); - const int m = 0; - [=] { - int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} + const int m = -1; + [] { + int arr[m]; // expected-error{{negative size}} } (); - [=] () -> bool { - int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} - return &m == 0; + [&] { + int arr[m]; // expected-error{{negative size}} + } (); + + [=] { + int arr[m]; // expected-error{{negative size}} } (); [m] { - int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} + int arr[m]; // expected-error{{negative size}} } (); } } @@ -240,3 +244,42 @@ namespace PR13854 { namespace PR14518 { auto f = [](void) { return __func__; }; // no-warning } + +namespace PR16708 { + auto L = []() { + auto ret = 0; + return ret; + return 0; + }; +} + +namespace TypeDeduction { + struct S {}; + void f() { + const S s {}; + S &&t = [&] { return s; } (); +#if __cplusplus <= 201103L + // expected-error@-2 {{drops qualifiers}} +#else + S &&u = [&] () -> auto { return s; } (); +#endif + } +} + + +namespace lambdas_in_NSDMIs { + template<class T> + struct L { + T t{}; + T t2 = ([](int a) { return [](int b) { return b; };})(t)(t); + }; + L<int> l; + + namespace non_template { + struct L { + int t = 0; + int t2 = ([](int a) { return [](int b) { return b; };})(t)(t); + }; + L l; + } +}
\ No newline at end of file diff --git a/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp b/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp new file mode 100644 index 0000000..17e1548 --- /dev/null +++ b/test/SemaCXX/libstdcxx_pointer_return_false_hack.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify + +// This is a test for an egregious hack in Clang that works around +// an issue with libstdc++-4.2's <tr1/hashtable> implementation. +// The code in question returns 'false' from a function with a pointer +// return type, which is ill-formed in C++11. + +#ifdef BE_THE_HEADER + +#pragma GCC system_header +namespace std { + namespace tr1 { + template<typename T> struct hashnode; + template<typename T> struct hashtable { + typedef hashnode<T> node; + node *find_node() { + // This is ill-formed in C++11, per core issue 903, but we accept + // it anyway in a system header. + return false; + } + }; + } +} + +#else + +#define BE_THE_HEADER +#include "libstdcxx_pointer_return_false_hack.cpp" + +auto *test1 = std::tr1::hashtable<int>().find_node(); + +void *test2() { return false; } // expected-error {{cannot initialize}} + +#endif diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp index 504df0d..1598d0e 100644 --- a/test/SemaCXX/linkage-spec.cpp +++ b/test/SemaCXX/linkage-spec.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wretained-language-linkage -DW_RETAINED_LANGUAGE_LINKAGE %s extern "C" { extern "C" void f(int); } @@ -41,7 +42,7 @@ namespace pr5430 { using namespace pr5430; extern "C" void pr5430::func(void) { } -// PR5404 +// PR5405 int f2(char *) { return 0; @@ -55,6 +56,18 @@ extern "C" } } +namespace PR5405 { + int f2b(char *) { + return 0; + } + + extern "C" { + int f2b(int) { + return f2b((char *)0); // ok + } + } +} + // PR6991 extern "C" typedef int (*PutcFunc_t)(int); @@ -114,3 +127,49 @@ namespace pr14958 { } int js::ObjectClass; } + +extern "C" void PR16167; // expected-error {{variable has incomplete type 'void'}} +extern void PR16167_0; // expected-error {{variable has incomplete type 'void'}} + +// PR7927 +enum T_7927 { + E_7927 +}; + +extern "C" void f_pr7927(int); + +namespace { + extern "C" void f_pr7927(int); + + void foo_pr7927() { + f_pr7927(E_7927); + f_pr7927(0); + ::f_pr7927(E_7927); + ::f_pr7927(0); + } +} + +void bar_pr7927() { + f_pr7927(E_7927); + f_pr7927(0); + ::f_pr7927(E_7927); + ::f_pr7927(0); +} + +namespace PR17337 { + extern "C++" { + class Foo; + extern "C" int bar3(Foo *y); + class Foo { + int x; + friend int bar3(Foo *y); +#ifdef W_RETAINED_LANGUAGE_LINKAGE +// expected-note@-5 {{previous declaration is here}} +// expected-warning@-3 {{retaining previous language linkage}} +#endif + }; + extern "C" int bar3(Foo *y) { + return y->x; + } + } +} diff --git a/test/SemaCXX/linkage2.cpp b/test/SemaCXX/linkage2.cpp index 3cfa981..075f5e7 100644 --- a/test/SemaCXX/linkage2.cpp +++ b/test/SemaCXX/linkage2.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -verify -fmodules %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=gnu++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions -Wno-local-type-template-args %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions -Wno-local-type-template-args -fmodules %s namespace test1 { int x; // expected-note {{previous definition is here}} @@ -65,7 +66,7 @@ namespace test6 { get_future(); template <class _Rp> struct shared_future<_Rp&> { - shared_future(future<_Rp&>&& __f); // expected-warning {{rvalue references are a C++11 extension}} + shared_future(future<_Rp&>&& __f); }; void f() { typedef int T; @@ -164,3 +165,51 @@ namespace test16 { } } } + +namespace test17 { + namespace { + struct I { + }; + } + template <typename T1, typename T2> void foo() {} + template <typename T, T x> void bar() {} // expected-note {{candidate function}} + inline void *g() { + struct L { + }; + // foo<L, I>'s linkage should be the merge of UniqueExternalLinkage (or + // InternalLinkage in c++11) and VisibleNoLinkage. The correct answer is + // NoLinkage in both cases. This means that using foo<L, I> as a template + // argument should fail. + return reinterpret_cast<void*>(bar<typeof(foo<L, I>), foo<L, I> >); // expected-error {{reinterpret_cast cannot resolve overloaded function 'bar' to type 'void *}} + } + void h() { + g(); + } +} + +namespace test18 { + template <typename T> struct foo { + template <T *P> static void f() {} + static void *g() { return (void *)f<&x>; } + static T x; + }; + template <typename T> T foo<T>::x; + inline void *f() { + struct S { + }; + return foo<S>::g(); + } + void *h() { return f(); } +} + +extern "C" void pr16247_foo(int); +static void pr16247_foo(double); +void pr16247_foo(int) {} +void pr16247_foo(double) {} + +namespace PR16247 { + extern "C" void pr16247_bar(int); + static void pr16247_bar(double); + void pr16247_bar(int) {} + void pr16247_bar(double) {} +} diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 515bcd4..239aecf 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -87,7 +87,7 @@ namespace test5 { } void test2(A &x) { - x->A::foo<int>(); // expected-error {{'test5::A' is not a pointer}} + x->A::foo<int>(); // expected-error {{'test5::A' is not a pointer; maybe you meant to use '.'?}} } } @@ -172,3 +172,55 @@ void f(int i) { j = 0; } } + +namespace PR15045 { + class Cl0 { + public: + int a; + }; + + int f() { + Cl0 c; + return c->a; // expected-error {{member reference type 'PR15045::Cl0' is not a pointer; maybe you meant to use '.'?}} + } + + struct bar { + void func(); // expected-note {{'func' declared here}} + }; + + struct foo { + bar operator->(); // expected-note 2 {{'->' applied to return value of the operator->() declared here}} + }; + + template <class T> void call_func(T t) { + t->func(); // expected-error-re 2 {{member reference type 'PR15045::bar' is not a pointer$}} \ + // expected-note {{did you mean to use '.' instead?}} + } + + void test_arrow_on_non_pointer_records() { + bar e; + foo f; + + // Show that recovery has happened by also triggering typo correction + e->Func(); // expected-error {{member reference type 'PR15045::bar' is not a pointer; maybe you meant to use '.'?}} \ + // expected-error {{no member named 'Func' in 'PR15045::bar'; did you mean 'func'?}} + + // Make sure a fixit isn't given in the case that the '->' isn't actually + // the problem (the problem is with the return value of an operator->). + f->func(); // expected-error-re {{member reference type 'PR15045::bar' is not a pointer$}} + + call_func(e); // expected-note {{in instantiation of function template specialization 'PR15045::call_func<PR15045::bar>' requested here}} + + call_func(f); // expected-note {{in instantiation of function template specialization 'PR15045::call_func<PR15045::foo>' requested here}} + } +} + +namespace pr16676 { + struct S { int i; }; + struct T { S* get_s(); }; + int f(S* s) { + T t; + return t.get_s // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}} + .i; // expected-error {{member reference type 'pr16676::S *' is a pointer; maybe you meant to use '->'}} + } +} diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 19e8e75..6e4fd5d 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -89,3 +89,14 @@ namespace PR14838 { const function &r; // expected-note {{reference member declared here}} } af; } + +namespace rdar14084171 { + struct Point { // expected-note 3 {{candidate constructor}} + double x; + double y; + }; + struct Sprite { + Point location = Point(0,0); // expected-error {{no matching constructor for initialization of 'rdar14084171::Point'}} + }; + void f(Sprite& x) { x = x; } +} diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp index 7dca121..aee8e2e 100644 --- a/test/SemaCXX/member-pointer-ms.cpp +++ b/test/SemaCXX/member-pointer-ms.cpp @@ -5,8 +5,6 @@ // 2012, which supports C++11 and static_assert. It should pass for both 64-bit // and 32-bit x86. // -// expected-no-diagnostics - // Test the size of various member pointer combinations: // - complete and incomplete // - single, multiple, and virtual inheritance (and unspecified for incomplete) @@ -165,3 +163,6 @@ struct MemPtrInTemplate { int T::*data_ptr; void (T::*func_ptr)(); }; + +int Virtual::*CastTest = reinterpret_cast<int Virtual::*>(&AA::x); + // expected-error@-1 {{cannot reinterpret_cast from member pointer type}} diff --git a/test/SemaCXX/microsoft-dtor-lookup.cpp b/test/SemaCXX/microsoft-dtor-lookup.cpp new file mode 100644 index 0000000..d264bab --- /dev/null +++ b/test/SemaCXX/microsoft-dtor-lookup.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi itanium -fsyntax-only %s +// RUN: %clang_cc1 -triple i686-pc-win32 -cxx-abi microsoft -verify -DMSVC_ABI %s + +namespace Test1 { + +// Should be accepted under the Itanium ABI (first RUN line) but rejected +// under the Microsoft ABI (second RUN line), as Microsoft ABI requires +// operator delete() lookups to be done at all virtual destructor declaration +// points. + +struct A { + void operator delete(void *); // expected-note {{member found by ambiguous name lookup}} +}; + +struct B { + void operator delete(void *); // expected-note {{member found by ambiguous name lookup}} +}; + +struct C : A, B { + ~C(); +}; + +struct VC : A, B { + virtual ~VC(); // expected-error {{member 'operator delete' found in multiple base classes of different types}} +}; + +} + +namespace Test2 { + +// In the MSVC ABI, functions must destroy their aggregate arguments. foo +// requires a dtor for B, but we can't implicitly define it because ~A is +// private. bar should be able to call A's private dtor without error, even +// though MSVC rejects bar. + +class A { +private: + ~A(); // expected-note 2{{declared private here}} + int a; +}; + +struct B : public A { // expected-error {{base class 'Test2::A' has private destructor}} + int b; +}; + +struct C { + ~C(); + int c; +}; + +struct D { + // D has a non-trivial implicit dtor that destroys C. + C o; +}; + +void foo(B b) { } // expected-note {{implicit destructor for 'Test2::B' first required here}} +void bar(A a) { } // expected-error {{variable of type 'Test2::A' has private destructor}} +void baz(D d) { } // no error + +} + +#ifdef MSVC_ABI +namespace Test3 { + +class A { + A(); + ~A(); // expected-note 2{{implicitly declared private here}} + friend void bar(A); + int a; +}; + +void bar(A a) { } +void baz(A a) { } // expected-error {{variable of type 'Test3::A' has private destructor}} + +// MSVC accepts foo() but we reject it for consistency with Itanium. MSVC also +// rejects this if A has a copy ctor or if we call A's ctor. +void foo(A *a) { + bar(*a); // expected-error {{temporary of type 'Test3::A' has private destructor}} +} +} +#endif + +namespace Test4 { +// Don't try to access the dtor of an incomplete on a function declaration. +class A; +void foo(A a); +} diff --git a/test/SemaCXX/microsoft-new-delete.cpp b/test/SemaCXX/microsoft-new-delete.cpp new file mode 100644 index 0000000..e0d25dc --- /dev/null +++ b/test/SemaCXX/microsoft-new-delete.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s +// expected-no-diagnostics + +#include <stddef.h> + +struct arbitrary_t {} arbitrary; +void *operator new(size_t size, arbitrary_t); + +void f() { + // Expect no error in MSVC compatibility mode + int *p = new(arbitrary) int[4]; +} diff --git a/test/SemaCXX/missing-members.cpp b/test/SemaCXX/missing-members.cpp index 529ba10..619bc61 100644 --- a/test/SemaCXX/missing-members.cpp +++ b/test/SemaCXX/missing-members.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s namespace A { namespace B { - class C { }; + class C { }; // expected-note 2 {{'A::B::C' declared here}} struct S { }; union U { }; } @@ -19,8 +19,12 @@ namespace B { void g() { A::B::D::E; // expected-error {{no member named 'D' in namespace 'A::B'}} - B::B::C::D; // expected-error {{no member named 'C' in 'B::B'}} - ::C::D; // expected-error {{no member named 'C' in the global namespace}} + // FIXME: The typo corrections below should be suppressed since A::B::C + // doesn't have a member named D. + B::B::C::D; // expected-error {{no member named 'C' in 'B::B'; did you mean 'A::B::C'?}} \ + // expected-error {{no member named 'D' in 'A::B::C'}} + ::C::D; // expected-error {{no member named 'C' in the global namespace; did you mean 'A::B::C'?}}\ + // expected-error {{no member named 'D' in 'A::B::C'}} } int A::B::i = 10; // expected-error {{no member named 'i' in namespace 'A::B'}} diff --git a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp index 40bcf45..6195e03 100644 --- a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp +++ b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp @@ -19,7 +19,7 @@ namespace fizbin { // expected-note{{'fizbin::nested::lessFoobar' declared here}} class dummy { // expected-note 2 {{'fizbin::dummy' declared here}} public: - static bool moreFoobar() { return false; } // expected-note{{'moreFoobar' declared here}} + static bool morebar() { return false; } // expected-note{{'morebar' declared here}} }; } void Check() { // expected-note{{'Check' declared here}} @@ -29,9 +29,9 @@ void Check() { // expected-note{{'Check' declared here}} if (lessFoobar()) Double(7); // expected-error{{use of undeclared identifier 'lessFoobar'; did you mean 'fizbin::nested::lessFoobar'?}} if (baztool::toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'baztool'; did you mean 'fizbin::baztool'?}} if (nested::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'nested'; did you mean 'fizbin::nested'?}} - if (dummy::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} - if (dummy::mreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} \ - // expected-error{{no member named 'mreFoobar' in 'fizbin::dummy'; did you mean 'moreFoobar'?}} + if (dummy::morebar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} + if (dummy::mrebar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} \ + // expected-error{{no member named 'mrebar' in 'fizbin::dummy'; did you mean 'morebar'?}} if (moFoobin()) Double(7); // expected-error{{use of undeclared identifier 'moFoobin'}} } diff --git a/test/SemaCXX/ms-overload-entry-point.cpp b/test/SemaCXX/ms-overload-entry-point.cpp new file mode 100644 index 0000000..67fed01 --- /dev/null +++ b/test/SemaCXX/ms-overload-entry-point.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -triple i386-pc-win32 %s + +template <typename T> +int wmain() { // expected-error{{'wmain' cannot be a template}} + return 0; +} + +namespace { +int WinMain(void) { return 0; } +int WinMain(int) { return 0; } +} + +void wWinMain(void) {} // expected-note{{previous definition is here}} +void wWinMain(int) {} // expected-error{{conflicting types for 'wWinMain'}} + +int foo() { + wmain<void>(); // expected-error{{no matching function for call to 'wmain'}} + wmain<int>(); // expected-error{{no matching function for call to 'wmain'}} + WinMain(); + return 0; +} diff --git a/test/SemaCXX/ms-wchar.cpp b/test/SemaCXX/ms-wchar.cpp new file mode 100644 index 0000000..878d8ca --- /dev/null +++ b/test/SemaCXX/ms-wchar.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -triple i386-pc-win32 %s + +wchar_t f(); +__wchar_t f(); // No error, wchar_t and __wchar_t are the same type. + +__wchar_t g = L'a'; +__wchar_t s[] = L"Hello world!"; + +unsigned short t[] = L"Hello world!"; // expected-error{{array initializer must be an initializer list}} + +wchar_t u[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}} +__wchar_t v[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}} diff --git a/test/SemaCXX/ms_struct.cpp b/test/SemaCXX/ms_struct.cpp new file mode 100644 index 0000000..37fa9a7 --- /dev/null +++ b/test/SemaCXX/ms_struct.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin9 -std=c++11 %s +// expected-no-diagnostics + +#pragma ms_struct on + +struct A { + unsigned long a:4; + unsigned char b; +}; + +struct B : public A { + unsigned long c:16; + int d; + B(); +}; + +static_assert(__builtin_offsetof(B, d) == 12, + "We can't allocate the bitfield into the padding under ms_struct");
\ No newline at end of file diff --git a/test/SemaCXX/ms_wide_bitfield.cpp b/test/SemaCXX/ms_wide_bitfield.cpp new file mode 100644 index 0000000..d917390 --- /dev/null +++ b/test/SemaCXX/ms_wide_bitfield.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only -mms-bitfields -verify %s 2>&1 + +struct A { + char a : 9; // expected-error{{size of bit-field 'a' (9 bits) exceeds size of its type (8 bits)}} + int b : 33; // expected-error{{size of bit-field 'b' (33 bits) exceeds size of its type (32 bits)}} + bool c : 9; // expected-error{{size of bit-field 'c' (9 bits) exceeds size of its type (8 bits)}} +}; + +int a[sizeof(A) == 1 ? 1 : -1]; diff --git a/test/SemaCXX/neon-vector-types.cpp b/test/SemaCXX/neon-vector-types.cpp index 336fcd4..c2953d7 100644 --- a/test/SemaCXX/neon-vector-types.cpp +++ b/test/SemaCXX/neon-vector-types.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify "-triple" "thumbv7-apple-ios3.0.0" %s +// RUN: %clang_cc1 -fsyntax-only -verify "-triple" "thumbv7-apple-ios3.0.0" -target-feature +neon %s // rdar://9208404 typedef int MP4Err; diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 7239646..df4f1b2 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify -fblocks %s namespace A { struct C { static int cx; @@ -50,6 +50,7 @@ namespace B { void f1() { void A::Af(); // expected-error {{definition or redeclaration of 'Af' not allowed inside a function}} + void (^x)() = ^{ void A::Af(); }; // expected-error {{definition or redeclaration of 'Af' not allowed inside a block}} } void f2() { @@ -166,9 +167,7 @@ void N::f() { } // okay struct Y; // expected-note{{forward declaration of 'Y'}} Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}} -X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \ - // expected-error{{C++ requires a type specifier for all declarations}} \ - // expected-error{{only constructors take base initializers}} +X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} struct foo_S { static bool value; @@ -260,7 +259,7 @@ namespace PR8159 { namespace rdar7980179 { class A { void f0(); }; // expected-note {{previous}} - int A::f0() {} // expected-error {{out-of-line definition of 'rdar7980179::A::f0' differs from the declaration in the return type}} + int A::f0() {} // expected-error {{return type of out-of-line definition of 'rdar7980179::A::f0' differs}} } namespace alias = A; @@ -297,3 +296,16 @@ namespace NS { int foobar = a + longer_b; // expected-error {{use of undeclared identifier 'a'; did you mean 'NS::a'?}} \ // expected-error {{use of undeclared identifier 'longer_b'; did you mean 'NS::longer_b'?}} } + +// <rdar://problem/13853540> +namespace N { + struct X { }; + namespace N { + struct Foo { + struct N::X *foo(); // expected-error{{no struct named 'X' in namespace 'N::N'}} + }; + } +} + +namespace TypedefNamespace { typedef int F; }; +TypedefNamespace::F::NonexistentName BadNNSWithCXXScopeSpec; // expected-error {{expected a class or namespace}} diff --git a/test/SemaCXX/new-delete-0x.cpp b/test/SemaCXX/new-delete-0x.cpp index 9e3b492..a11392d 100644 --- a/test/SemaCXX/new-delete-0x.cpp +++ b/test/SemaCXX/new-delete-0x.cpp @@ -21,7 +21,9 @@ void bad_news(int *ip) 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}} + 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}} \ + expected-error {{a lambda expression may not appear inside of a constant expression}} } void good_deletes() diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 8b35295..7facd10 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -18,6 +18,13 @@ struct V : U { }; +inline void operator delete(void *); // expected-warning {{replacement function 'operator delete' cannot be declared 'inline'}} + +__attribute__((used)) +inline void *operator new(size_t) { // no warning, due to __attribute__((used)) + return 0; +} + // PR5823 void* operator new(const size_t); // expected-note 2 {{candidate}} void* operator new(size_t, int*); // expected-note 3 {{candidate}} @@ -116,8 +123,8 @@ struct X1 { }; struct X2 { - operator int*(); // expected-note {{candidate function}} - operator float*(); // expected-note {{candidate function}} + operator int*(); // expected-note {{conversion}} + operator float*(); // expected-note {{conversion}} }; void test_delete_conv(X0 x0, X1 x1, X2 x2) { @@ -209,7 +216,7 @@ struct X11 : X10 { // expected-error {{no suitable member 'operator delete' in ' }; void f() { - X11 x11; // expected-note {{implicit default destructor for 'X11' first required here}} + X11 x11; // expected-note {{implicit destructor for 'X11' first required here}} } struct X12 { @@ -394,7 +401,7 @@ namespace ArrayNewNeedsDtor { struct A { A(); private: ~A(); }; // expected-note {{declared private here}} struct B { B(); A a; }; // expected-error {{field of type 'ArrayNewNeedsDtor::A' has private destructor}} B *test9() { - return new B[5]; // expected-note {{implicit default destructor for 'ArrayNewNeedsDtor::B' first required here}} + return new B[5]; // expected-note {{implicit destructor for 'ArrayNewNeedsDtor::B' first required here}} } } diff --git a/test/SemaCXX/no-rtti.cpp b/test/SemaCXX/no-rtti.cpp index 7516705..a171b3c 100644 --- a/test/SemaCXX/no-rtti.cpp +++ b/test/SemaCXX/no-rtti.cpp @@ -8,3 +8,22 @@ void f() { (void)typeid(int); // expected-error {{cannot use typeid with -fno-rtti}} } + +namespace { +struct A { + virtual ~A(){}; +}; + +struct B : public A { + B() : A() {} +}; +} + +bool isa_B(A *a) { + return dynamic_cast<B *>(a) != 0; // expected-error {{cannot use dynamic_cast with -fno-rtti}} +} + +void* getMostDerived(A* a) { + // This cast does not use RTTI. + return dynamic_cast<void *>(a); +} diff --git a/test/SemaCXX/no-warn-unused-const-variables.cpp b/test/SemaCXX/no-warn-unused-const-variables.cpp new file mode 100644 index 0000000..c146ca0 --- /dev/null +++ b/test/SemaCXX/no-warn-unused-const-variables.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wno-unused-const-variable -verify %s + +namespace { + int i = 0; // expected-warning {{unused variable 'i'}} + const int j = 0;; +} diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index b49f63b..28798a4 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -64,6 +64,9 @@ nullptr_t f(nullptr_t null) (void)reinterpret_cast<uintptr_t>(nullptr); (void)reinterpret_cast<uintptr_t>(*pn); + // You can't reinterpret_cast nullptr to any integer + (void)reinterpret_cast<char>(nullptr); // expected-error {{cast from pointer to smaller type 'char' loses information}} + int *ip = *pn; if (*pn) { } diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp index a5f5d34..e6069ac 100644 --- a/test/SemaCXX/offsetof.cpp +++ b/test/SemaCXX/offsetof.cpp @@ -73,3 +73,13 @@ struct LtoRCheck { }; int ltor = __builtin_offsetof(struct LtoRCheck, a[LtoRCheck().f]); // \ expected-error {{reference to non-static member function must be called}} + +namespace PR17578 { +struct Base { + int Field; +}; +struct Derived : virtual Base { + void Fun() { (void)__builtin_offsetof(Derived, Field); } // expected-warning {{offset of on non-POD type}} \ + expected-error {{invalid application of 'offsetof' to a field of a virtual base}} +}; +} diff --git a/test/SemaCXX/operator-arrow-depth.cpp b/test/SemaCXX/operator-arrow-depth.cpp new file mode 100644 index 0000000..3e2ba8e --- /dev/null +++ b/test/SemaCXX/operator-arrow-depth.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -DMAX=128 -foperator-arrow-depth 128 +// RUN: %clang_cc1 -fsyntax-only -verify %s -DMAX=2 -foperator-arrow-depth 2 +// RUN: %clang -fsyntax-only -Xclang -verify %s -DMAX=10 -foperator-arrow-depth=10 + +template<int N> struct B; +template<int N> struct A { + B<N> operator->(); // expected-note +{{'operator->' declared here produces an object of type 'B<}} +}; +template<int N> struct B { + A<N-1> operator->(); // expected-note +{{'operator->' declared here produces an object of type 'A<}} +#if MAX != 2 + // expected-note-re@-2 {{(skipping (120|2) 'operator->'s in backtrace)}} +#endif +}; + +struct X { int n; }; +template<> struct B<1> { + X *operator->(); +}; + +A<MAX/2> good; +int n = good->n; + +B<MAX/2 + 1> bad; +int m = bad->n; // expected-error-re {{use of 'operator->' on type 'B<(2|10|128) / 2 \+ 1>' would invoke a sequence of more than (2|10|128) 'operator->' calls}} + // expected-note@-1 {{use -foperator-arrow-depth=N to increase 'operator->' limit}} diff --git a/test/SemaCXX/overload-decl.cpp b/test/SemaCXX/overload-decl.cpp index 9bba47a..fdb14cb 100644 --- a/test/SemaCXX/overload-decl.cpp +++ b/test/SemaCXX/overload-decl.cpp @@ -26,8 +26,14 @@ class X { void g(int, float); // expected-note {{previous declaration is here}} int g(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} - static void g(float); + static void g(float); // expected-note {{previous declaration is here}} static void g(int); // expected-error {{static and non-static member functions with the same parameter types cannot be overloaded}} + static void g(float); // expected-error {{class member cannot be redeclared}} + + void h(); // expected-note {{previous declaration is here}} \ + expected-note {{previous declaration is here}} + void h() __restrict; // expected-error {{class member cannot be redeclared}} \ + expected-error {{conflicting types for 'h'}} }; int main() {} // expected-note {{previous definition is here}} diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index e5b3fab..99105cb 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s class X { }; X operator+(X, X); @@ -387,8 +387,8 @@ void test_lookup_through_using() { namespace rdar9136502 { struct X { - int i(); - int i(int); + int i(); // expected-note{{possible target for call}} + int i(int); // expected-note{{possible target for call}} }; struct Y { @@ -396,7 +396,8 @@ namespace rdar9136502 { }; void f(X x, Y y) { - y << x.i; // expected-error{{reference to non-static member function must be called}} + y << x + .i; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } } @@ -440,3 +441,14 @@ namespace test10 { a[bar<float>]; } } + +struct InvalidOperatorEquals { + InvalidOperatorEquals operator=() = delete; // expected-error {{overloaded 'operator=' must be a binary operator}} +}; + +namespace PR7681 { + template <typename PT1, typename PT2> class PointerUnion; + void foo(PointerUnion<int*, float*> &Result) { + Result = 1; // expected-error {{no viable overloaded '='}} // expected-note {{type 'PointerUnion<int *, float *>' is incomplete}} + } +} diff --git a/test/SemaCXX/parentheses.cpp b/test/SemaCXX/parentheses.cpp new file mode 100644 index 0000000..b430b25 --- /dev/null +++ b/test/SemaCXX/parentheses.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify %s + +// PR16930, PR16727: +template<class Foo> +bool test(Foo f, int *array) +{ + return false && false || array[f.get()]; // expected-warning {{'&&' within '||'}} expected-note {{parentheses}} +} diff --git a/test/SemaCXX/pr13394-crash-on-invalid.cpp b/test/SemaCXX/pr13394-crash-on-invalid.cpp index 413c52a..841e3c2 100644 --- a/test/SemaCXX/pr13394-crash-on-invalid.cpp +++ b/test/SemaCXX/pr13394-crash-on-invalid.cpp @@ -9,8 +9,21 @@ namespace stretch_v1 { namespace gatekeeper_v1 { namespace gatekeeper_factory_v1 { struct closure_t { // expected-note {{'closure_t' declared here}} - gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean 'closure_t'?}} + gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean simply 'closure_t'?}} }; } - gatekeeper_v1::closure_t *x; // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1}} + // FIXME: Typo correction should remove the 'gatekeeper_v1::' name specifier + gatekeeper_v1::closure_t *x; // expected-error-re {{no type named 'closure_t' in namespace 'gatekeeper_v1'$}} } + +namespace Foo { +struct Base { + void Bar() {} // expected-note{{'Bar' declared here}} +}; +} + +struct Derived : public Foo::Base { + void test() { + Foo::Bar(); // expected-error{{no member named 'Bar' in namespace 'Foo'; did you mean simply 'Bar'?}} + } +}; diff --git a/test/SemaCXX/predefined-expr.cpp b/test/SemaCXX/predefined-expr.cpp new file mode 100644 index 0000000..257d44c --- /dev/null +++ b/test/SemaCXX/predefined-expr.cpp @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -std=c++1y -fblocks -fsyntax-only -verify %s +// PR16946 +// expected-no-diagnostics + +auto foo() { + static_assert(sizeof(__func__) == 4, "foo"); + static_assert(sizeof(__FUNCTION__) == 4, "foo"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 11, "auto foo()"); + return 0; +} + +auto bar() -> decltype(42) { + static_assert(sizeof(__func__) == 4, "bar"); + static_assert(sizeof(__FUNCTION__) == 4, "bar"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 10, "int bar()"); + return 0; +} + +// Within templates. +template <typename T> +int baz() { + static_assert(sizeof(__func__) == 4, "baz"); + static_assert(sizeof(__FUNCTION__) == 4, "baz"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "int baz() [T = int]"); + + []() { + static_assert(sizeof(__func__) == 11, "operator()"); + static_assert(sizeof(__FUNCTION__) == 11, "operator()"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 50, + "auto baz()::<anonymous class>::operator()() const"); + return 0; + } + (); + + ^{ + // FIXME: This is obviously wrong. + static_assert(sizeof(__func__) == 1, "__baz_block_invoke"); + static_assert(sizeof(__FUNCTION__) == 1, "__baz_block_invoke"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__baz_block_invoke"); + } + (); + + #pragma clang __debug captured + { + static_assert(sizeof(__func__) == 4, "baz"); + static_assert(sizeof(__FUNCTION__) == 4, "baz"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "int baz() [T = int]"); + } + + return 0; +} + +int main() { + static_assert(sizeof(__func__) == 5, "main"); + static_assert(sizeof(__FUNCTION__) == 5, "main"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 11, "int main()"); + + []() { + static_assert(sizeof(__func__) == 11, "operator()"); + static_assert(sizeof(__FUNCTION__) == 11, "operator()"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 51, + "auto main()::<anonymous class>::operator()() const"); + return 0; + } + (); + + ^{ + // FIXME: This is obviously wrong. + static_assert(sizeof(__func__) == 1, "__main_block_invoke"); + static_assert(sizeof(__FUNCTION__) == 1, "__main_block_invoke"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 1, "__main_block_invoke"); + } + (); + + #pragma clang __debug captured + { + static_assert(sizeof(__func__) == 5, "main"); + static_assert(sizeof(__FUNCTION__) == 5, "main"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 11, "int main()"); + + #pragma clang __debug captured + { + static_assert(sizeof(__func__) == 5, "main"); + static_assert(sizeof(__FUNCTION__) == 5, "main"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 11, "int main()"); + } + } + + []() { + #pragma clang __debug captured + { + static_assert(sizeof(__func__) == 11, "operator()"); + static_assert(sizeof(__FUNCTION__) == 11, "operator()"); + static_assert(sizeof(__PRETTY_FUNCTION__) == 51, + "auto main()::<anonymous class>::operator()() const"); + } + } + (); + + baz<int>(); + + return 0; +} diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index a14193c..23164fa 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -86,13 +86,13 @@ namespace a { namespace a { namespace a { // A1 namespace a { // A2 - int i; // expected-note{{'::a::a::a::i' declared here}} + int i; // expected-note{{'a::a::a::i' declared here}} } } } void test_a() { - a::a::i = 3; // expected-error{{no member named 'i' in namespace 'a::a'; did you mean '::a::a::a::i'?}} + a::a::i = 3; // expected-error{{no member named 'i' in namespace 'a::a'; did you mean 'a::a::a::i'?}} a::a::a::i = 4; a::a::j = 3; // expected-error-re{{no member named 'j' in namespace 'a::a'$}} } @@ -149,6 +149,6 @@ namespace PR6830 { } namespace pr12339 { - extern "C" void i; + extern "C" void i; // expected-error{{variable has incomplete type 'void'}} pr12339::FOO // expected-error{{no type named 'FOO' in namespace 'pr12339'}} } // expected-error{{expected unqualified-id}} diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index 4f3dab0..37fc2a8 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -137,3 +137,10 @@ namespace PR8608 { // The following crashed trying to recursively evaluate the LValue. const int &do_not_crash = do_not_crash; // expected-warning{{reference 'do_not_crash' is not yet bound to a value when used within its own initialization}} + +namespace ExplicitRefInit { + // This is invalid: we can't copy-initialize an 'A' temporary using an + // explicit constructor. + struct A { explicit A(int); }; + const A &a(0); // expected-error {{reference to type 'const ExplicitRefInit::A' could not bind to an rvalue of type 'int'}} +} diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index de276ae..90c9317 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -276,6 +276,27 @@ namespace test15 { } namespace test16 { + struct S { int n; }; + int f() { + goto x; // expected-error {{goto into protected scope}} + const S &s = S(); // expected-note {{jump bypasses variable initialization}} +x: return s.n; + } +} + +#if __cplusplus >= 201103L +namespace test17 { + struct S { int get(); private: int n; }; + int f() { + goto x; // expected-error {{goto into protected scope}} + S s = {}; // expected-note {{jump bypasses variable initialization}} +x: return s.get(); + } +} +#endif + +// This test must be last, because the error prohibits further jump diagnostics. +namespace testInvalid { Invalid inv; // expected-error {{unknown type name}} // Make sure this doesn't assert. void fn() diff --git a/test/SemaCXX/self-comparison.cpp b/test/SemaCXX/self-comparison.cpp new file mode 100644 index 0000000..fb15ec8 --- /dev/null +++ b/test/SemaCXX/self-comparison.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int foo(int x) { + return x == x; // expected-warning {{self-comparison always evaluates to true}} +} + +struct X { + bool operator==(const X &x); +}; + +struct A { + int x; + X x2; + int a[3]; + int b[3]; + bool f() { return x == x; } // expected-warning {{self-comparison always evaluates to true}} + bool g() { return x2 == x2; } // no-warning + bool h() { return a == b; } // expected-warning {{array comparison always evaluates to false}} + bool i() { + int c[3]; + return a == c; // expected-warning {{array comparison always evaluates to false}} + } +}; diff --git a/test/SemaCXX/static-data-member.cpp b/test/SemaCXX/static-data-member.cpp new file mode 100644 index 0000000..9fe87b1 --- /dev/null +++ b/test/SemaCXX/static-data-member.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -w %s + +struct ABC { + static double a; + static double b; + static double c; + static double d; + static double e; + static double f; +}; + +double ABC::a = 1.0; +extern double ABC::b = 1.0; // expected-error {{static data member definition cannot specify a storage class}} +static double ABC::c = 1.0; // expected-error {{'static' can only be specified inside the class definition}} +__private_extern__ double ABC::d = 1.0; // expected-error {{static data member definition cannot specify a storage class}} +auto double ABC::e = 1.0; // expected-error {{static data member definition cannot specify a storage class}} +register double ABC::f = 1.0; // expected-error {{static data member definition cannot specify a storage class}} diff --git a/test/SemaCXX/storage-class.cpp b/test/SemaCXX/storage-class.cpp index 7412184..decf1e7 100644 --- a/test/SemaCXX/storage-class.cpp +++ b/test/SemaCXX/storage-class.cpp @@ -4,4 +4,4 @@ extern int PR6495b = 42; // expected-warning{{'extern' variable has an initializ extern const int PR6495c[] = {42,43,44}; extern struct Test1 {}; // expected-warning {{'extern' is not permitted on a declaration of a type}} -extern "C" struct Test0 {}; // no warning +extern "C" struct Test0 { int x; }; // no warning diff --git a/test/SemaCXX/string-init.cpp b/test/SemaCXX/string-init.cpp new file mode 100644 index 0000000..7e62d18 --- /dev/null +++ b/test/SemaCXX/string-init.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void f() { + char a1[] = "a"; // No error. + char a2[] = u8"a"; // No error. + char a3[] = u"a"; // expected-error{{initializing char array with wide string literal}} + char a4[] = U"a"; // expected-error{{initializing char array with wide string literal}} + char a5[] = L"a"; // expected-error{{initializing char array with wide string literal}} + + wchar_t b1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}} + wchar_t b2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}} + wchar_t b3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}} + wchar_t b4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}} + wchar_t b5[] = L"a"; // No error. + + char16_t c1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}} + char16_t c2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}} + char16_t c3[] = u"a"; // No error. + char16_t c4[] = U"a"; // expected-error{{initializing wide char array with incompatible wide string literal}} + char16_t c5[] = L"a"; // expected-error{{initializing wide char array with incompatible wide string literal}} + + char32_t d1[] = "a"; // expected-error{{initializing wide char array with non-wide string literal}} + char32_t d2[] = u8"a"; // expected-error{{initializing wide char array with non-wide string literal}} + char32_t d3[] = u"a"; // expected-error{{initializing wide char array with incompatible wide string literal}} + char32_t d4[] = U"a"; // No error. + char32_t d5[] = L"a"; // expected-error{{initializing wide char array with incompatible wide string literal}} + + int e1[] = "a"; // expected-error{{array initializer must be an initializer list}} + int e2[] = u8"a"; // expected-error{{array initializer must be an initializer list}} + int e3[] = u"a"; // expected-error{{array initializer must be an initializer list}} + int e4[] = U"a"; // expected-error{{array initializer must be an initializer list}} + int e5[] = L"a"; // expected-error{{array initializer must be an initializer list}} +} + +void g() { + char a[] = 1; // expected-error{{array initializer must be an initializer list or string literal}} + wchar_t b[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}} + char16_t c[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}} + char32_t d[] = 1; // expected-error{{array initializer must be an initializer list or wide string literal}} +} diff --git a/test/SemaCXX/string-plus-char.cpp b/test/SemaCXX/string-plus-char.cpp new file mode 100644 index 0000000..00a2c45 --- /dev/null +++ b/test/SemaCXX/string-plus-char.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +class A { +public: + A(): str() { } + A(const char *p) { } + A(char *p) : str(p + 'a') { } // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + A& operator+(const char *p) { return *this; } + A& operator+(char ch) { return *this; } + char * str; +}; + +void f(const char *s) { + A a = s + 'a'; // // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + a = a + s + 'b'; // no-warning + + char *str = 0; + char *str2 = str + 'c'; // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + + const char *constStr = s + 'c'; // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + + str = 'c' + str;// expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + + wchar_t *wstr; + wstr = wstr + L'c'; // expected-warning {{adding 'wchar_t' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + str2 = str + u'a'; // expected-warning {{adding 'char16_t' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}} + + // no-warning + char c = 'c'; + str = str + c; + str = c + str; +} diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp index 5c59578..e1b95ba 100644 --- a/test/SemaCXX/struct-class-redecl.cpp +++ b/test/SemaCXX/struct-class-redecl.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -Wmismatched-tags -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wmismatched-tags %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -fsyntax-only -Wmismatched-tags %s 2>&1 | FileCheck %s class X; // expected-note 2{{here}} typedef struct X * X_t; // expected-warning{{previously declared}} union X { int x; float y; }; // expected-error{{use of 'X' with tag type that does not match previous declaration}} diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp index 517faa9..392dcd8 100644 --- a/test/SemaCXX/switch.cpp +++ b/test/SemaCXX/switch.cpp @@ -85,3 +85,18 @@ void local_class(int n) { }(); } } + +namespace Conversion { + struct S { + explicit operator int(); // expected-note {{conversion}} + }; + template<typename T> void f(T t) { + switch (t) { // expected-error {{explicit conversion}} + case 0: + return; + default: + break; + } + } + template void f(S); // expected-note {{instantiation of}} +} diff --git a/test/SemaCXX/trailing-return-0x.cpp b/test/SemaCXX/trailing-return-0x.cpp index bd601db..f7e3433 100644 --- a/test/SemaCXX/trailing-return-0x.cpp +++ b/test/SemaCXX/trailing-return-0x.cpp @@ -94,3 +94,11 @@ namespace DR1608 { auto f() -> decltype((*this)[0]); // expected-error {{cannot be overloaded}} }; } + +namespace PR16273 { + struct A { + template <int N> void f(); + auto g()->decltype(this->f<0>()); + }; +} + diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index aa18ff4..3e47921 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fms-extensions -Wno-microsoft %s #define T(b) (b) ? 1 : -1 #define F(b) (b) ? -1 : 1 @@ -308,6 +308,37 @@ void is_final() { int arr[F(__is_final(PotentiallyFinal<float>))]; } } +struct SealedClass sealed { +}; + +template<typename T> +struct PotentiallySealed { }; + +template<typename T> +struct PotentiallySealed<T*> sealed { }; + +template<> +struct PotentiallySealed<int> sealed { }; + +void is_sealed() +{ + { int arr[T(__is_sealed(SealedClass))]; } + { int arr[T(__is_sealed(PotentiallySealed<float*>))]; } + { int arr[T(__is_sealed(PotentiallySealed<int>))]; } + + { int arr[F(__is_sealed(int))]; } + { int arr[F(__is_sealed(Union))]; } + { int arr[F(__is_sealed(Int))]; } + { int arr[F(__is_sealed(IntAr))]; } + { int arr[F(__is_sealed(UnionAr))]; } + { int arr[F(__is_sealed(Derives))]; } + { int arr[F(__is_sealed(ClassType))]; } + { int arr[F(__is_sealed(cvoid))]; } + { int arr[F(__is_sealed(IntArNB))]; } + { int arr[F(__is_sealed(HasAnonymousUnion))]; } + { int arr[F(__is_sealed(PotentiallyFinal<float>))]; } +} + typedef HasVirt Polymorph; struct InheritPolymorph : Polymorph {}; @@ -1072,6 +1103,9 @@ void is_trivially_copyable2() int t31[F(__is_trivially_copyable(SuperNonTrivialStruct))]; int t32[F(__is_trivially_copyable(NonTCStruct))]; int t33[F(__is_trivially_copyable(ExtDefaulted))]; + + int t34[T(__is_trivially_copyable(const int))]; + int t35[F(__is_trivially_copyable(volatile int))]; } struct CStruct { @@ -1244,14 +1278,14 @@ void has_trivial_default_constructor() { void has_trivial_move_constructor() { // n3376 12.8 [class.copy]/12 - // A copy/move constructor for class X is trivial if it is not - // user-provided, its declared parameter type is the same as + // A copy/move constructor for class X is trivial if it is not + // user-provided, its declared parameter type is the same as // if it had been implicitly declared, and if - // — class X has no virtual functions (10.3) and no virtual + // - class X has no virtual functions (10.3) and no virtual // base classes (10.1), and - // — the constructor selected to copy/move each direct base + // - the constructor selected to copy/move each direct base // class subobject is trivial, and - // — for each non-static data member of X that is of class + // - for each non-static data member of X that is of class // type (or array thereof), the constructor selected // to copy/move that member is trivial; // otherwise the copy/move constructor is non-trivial. @@ -1445,14 +1479,14 @@ void has_nothrow_move_assign() { void has_trivial_move_assign() { // n3376 12.8 [class.copy]/25 - // A copy/move assignment operator for class X is trivial if it - // is not user-provided, its declared parameter type is the same + // A copy/move assignment operator for class X is trivial if it + // is not user-provided, its declared parameter type is the same // as if it had been implicitly declared, and if: - // — class X has no virtual functions (10.3) and no virtual base + // - class X has no virtual functions (10.3) and no virtual base // classes (10.1), and - // — the assignment operator selected to copy/move each direct + // - the assignment operator selected to copy/move each direct // base class subobject is trivial, and - // — for each non-static data member of X that is of class type + // - for each non-static data member of X that is of class type // (or array thereof), the assignment operator // selected to copy/move that member is trivial; { int arr[T(__has_trivial_move_assign(Int))]; } @@ -1571,7 +1605,7 @@ template<typename T> struct DerivedB : BaseA<T> { }; template<typename T> struct CrazyDerived : T { }; -class class_forward; // expected-note {{forward declaration of 'class_forward'}} +class class_forward; // expected-note 2 {{forward declaration of 'class_forward'}} template <typename Base, typename Derived> void isBaseOfT() { @@ -1770,6 +1804,8 @@ void is_trivial() { int arr[F(__is_trivial(cvoid))]; } } +template<typename T> struct TriviallyConstructibleTemplate {}; + void trivial_checks() { { int arr[T(__is_trivially_copyable(int))]; } @@ -1848,6 +1884,11 @@ void trivial_checks() { int arr[F((__is_trivially_constructible(ExtDefaulted, ExtDefaulted &&)))]; } + { int arr[T((__is_trivially_constructible(TriviallyConstructibleTemplate<int>)))]; } + { int arr[F((__is_trivially_constructible(class_forward)))]; } // expected-error {{incomplete type 'class_forward' used in type trait expression}} + { int arr[F((__is_trivially_constructible(class_forward[])))]; } + { int arr[F((__is_trivially_constructible(void)))]; } + { int arr[T((__is_trivially_assignable(int&, int)))]; } { int arr[T((__is_trivially_assignable(int&, int&)))]; } { int arr[T((__is_trivially_assignable(int&, int&&)))]; } diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp new file mode 100644 index 0000000..525d11b --- /dev/null +++ b/test/SemaCXX/typo-correction-pt2.cpp @@ -0,0 +1,201 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s +// +// FIXME: This file is overflow from test/SemaCXX/typo-correction.cpp due to a +// hard-coded limit of 20 different typo corrections Sema::CorrectTypo will +// attempt within a single file (which is to avoid having very broken files take +// minutes to finally be rejected by the parser). + +namespace bogus_keyword_suggestion { +void test() { + status = "OK"; // expected-error-re {{use of undeclared identifier 'status'$}} + return status; // expected-error-re {{use of undeclared identifier 'status'$}} + } +} + +namespace PR13387 { +struct A { + void CreateFoo(float, float); + void CreateBar(float, float); +}; +struct B : A { + using A::CreateFoo; + void CreateFoo(int, int); +}; +void f(B &x) { + x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}} +} +} + +struct DataStruct {void foo();}; +struct T { + DataStruct data_struct; + void f(); +}; +// should be void T::f(); +void f() { + data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}} +} + +namespace PR12287 { +class zif { + void nab(int); +}; +void nab(); // expected-note{{'::PR12287::nab' declared here}} +void zif::nab(int) { + nab(); // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::PR12287::nab'?}} +} +} + +namespace TemplateFunction { +template <class T> +void A(T) { } // expected-note {{'::TemplateFunction::A' declared here}} + +template <class T> +void B(T) { } // expected-note {{'::TemplateFunction::B' declared here}} + +class Foo { + public: + void A(int, int) {} + void B() {} +}; + +void test(Foo F, int num) { + F.A(num); // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}} + F.B(num); // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}} +} +} +namespace using_suggestion_val_dropped_specifier { +void FFF() {} // expected-note {{'::using_suggestion_val_dropped_specifier::FFF' declared here}} +namespace N { } +using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean '::using_suggestion_val_dropped_specifier::FFF'?}} +} + +namespace class_member_typo_corrections { +class Outer { +public: + class Inner {}; // expected-note {{'Outer::Inner' declared here}} + Inner MyMethod(Inner arg); +}; + +Inner Outer::MyMethod(Inner arg) { // expected-error {{unknown type name 'Inner'; did you mean 'Outer::Inner'?}} + return Inner(); +} + +class Result { +public: + enum ResultType { + ENTITY, // expected-note {{'Result::ENTITY' declared here}} + PREDICATE, // expected-note {{'Result::PREDICATE' declared here}} + LITERAL // expected-note {{'Result::LITERAL' declared here}} + }; + + ResultType type(); +}; + +void test() { + Result result_cell; + switch (result_cell.type()) { + case ENTITY: // expected-error {{use of undeclared identifier 'ENTITY'; did you mean 'Result::ENTITY'?}} + case LITERAL: // expected-error {{use of undeclared identifier 'LITERAL'; did you mean 'Result::LITERAL'?}} + case PREDICAT: // expected-error {{use of undeclared identifier 'PREDICAT'; did you mean 'Result::PREDICATE'?}} + break; + } +} + +class Figure { + enum ResultType { + SQUARE, + TRIANGLE, + CIRCLE + }; + +public: + ResultType type(); +}; + +void testAccess() { + Figure obj; + switch (obj.type()) { // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}} + case SQUARE: // expected-error-re {{use of undeclared identifier 'SQUARE'$}} + case TRIANGLE: // expected-error-re {{use of undeclared identifier 'TRIANGLE'$}} + case CIRCE: // expected-error-re {{use of undeclared identifier 'CIRCE'$}} + break; + } +} +} + +long readline(const char *, char *, unsigned long); +void assign_to_unknown_var() { + deadline_ = 1; // expected-error-re {{use of undeclared identifier 'deadline_'$}} +} + +namespace no_ns_before_dot { +namespace re2 {} +void test() { + req.set_check(false); // expected-error-re {{use of undeclared identifier 'req'$}} +} +} + +namespace PR17394 { + class A { + protected: + long zzzzzzzzzz; + }; + class B : private A {}; + B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{} +} + +namespace correct_fields_in_member_funcs { +struct S { + int my_member; // expected-note {{'my_member' declared here}} + void f() { my_menber = 1; } // expected-error {{use of undeclared identifier 'my_menber'; did you mean 'my_member'?}} +}; +} + +namespace PR17019 { + template<class F> + struct evil { + evil(F de) { // expected-note {{'de' declared here}} + de_; // expected-error {{use of undeclared identifier 'de_'; did you mean 'de'?}} \ + // expected-warning {{expression result unused}} + } + ~evil() { + de_->bar() // expected-error {{use of undeclared identifier 'de_'}} + } + }; + + void meow() { + evil<int> Q(0); // expected-note {{in instantiation of member function}} + } +} + +namespace fix_class_name_qualifier { +class MessageHeaders {}; +class MessageUtils { + public: + static void ParseMessageHeaders(int, int); // expected-note {{'MessageUtils::ParseMessageHeaders' declared here}} +}; + +void test() { + // No, we didn't mean to call MessageHeaders::MessageHeaders. + MessageHeaders::ParseMessageHeaders(5, 4); // expected-error {{no member named 'ParseMessageHeaders' in 'fix_class_name_qualifier::MessageHeaders'; did you mean 'MessageUtils::ParseMessageHeaders'?}} +} +} + +namespace PR18213 { // expected-note {{'PR18213' declared here}} +struct WrapperInfo { + int i; +}; + +template <typename T> struct Wrappable { + static WrapperInfo kWrapperInfo; +}; + +// Note the space before "::PR18213" is intended and needed, as it highlights +// the actual typo, which is the leading "::". +// TODO: Suggest removing the "::" from "::PR18213" (the right correction) +// instead of incorrectly suggesting dropping "PR18213::WrapperInfo::". +template <> +PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 }; // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \ + // expected-error {{C++ requires a type specifier for all declarations}} +} diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp index caa6355..4047e6a 100644 --- a/test/SemaCXX/typo-correction.cpp +++ b/test/SemaCXX/typo-correction.cpp @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s +// +// WARNING: Do not add more typo correction test cases to this file lest you run +// afoul the hard-coded limit (escape hatch) of 20 different typos whose +// correction was attempted by Sema::CorrectTypo struct errc { int v_; @@ -213,10 +217,14 @@ namespace PR13051 { operator bool() const; }; - void f() { - f(&S<int>::tempalte f<int>); // expected-error{{did you mean 'template'?}} - f(&S<int>::opeartor bool); // expected-error{{did you mean 'operator'?}} - f(&S<int>::foo); // expected-error-re{{no member named 'foo' in 'PR13051::S<int>'$}} + void foo(); // expected-note{{'foo' declared here}} + void g(void(*)()); + void g(bool(S<int>::*)() const); + + void test() { + g(&S<int>::tempalte f<int>); // expected-error{{did you mean 'template'?}} + g(&S<int>::opeartor bool); // expected-error{{did you mean 'operator'?}} + g(&S<int>::foo); // expected-error{{no member named 'foo' in 'PR13051::S<int>'; did you mean simply 'foo'?}} } } @@ -230,33 +238,67 @@ class foo { }; // expected-note{{'foo' declared here}} class bar : boo { }; // expected-error{{unknown class name 'boo'; did you mean 'foo'?}} } -namespace bogus_keyword_suggestion { -void test() { - status = "OK"; // expected-error-re{{use of undeclared identifier 'status'$}} - return status; // expected-error-re{{use of undeclared identifier 'status'$}} - } +namespace outer { + void somefunc(); // expected-note{{'::outer::somefunc' declared here}} + void somefunc(int, int); // expected-note{{'::outer::somefunc' declared here}} + + namespace inner { + void somefunc(int) { + someFunc(); // expected-error{{use of undeclared identifier 'someFunc'; did you mean '::outer::somefunc'?}} + someFunc(1, 2); // expected-error{{use of undeclared identifier 'someFunc'; did you mean '::outer::somefunc'?}} + } + } } -namespace PR13387 { -struct A { - void CreateFoo(float, float); // expected-note {{'CreateFoo' declared here}} - void CreateBar(float, float); -}; -struct B : A { - using A::CreateFoo; - void CreateFoo(int, int); -}; -void f(B &x) { - x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}} +namespace b6956809_test1 { + struct A {}; + struct B {}; + + struct S1 { + void method(A*); // no note here + void method(B*); + }; + + void test1() { + B b; + S1 s; + s.methodd(&b); // expected-error{{no member named 'methodd' in 'b6956809_test1::S1'; did you mean 'method'}} + } + + struct S2 { + S2(); + void method(A*) const; // expected-note{{candidate function not viable}} + private: + void method(B*); // expected-note{{candidate function not viable}} + }; + + void test2() { + B b; + const S2 s; + s.methodd(&b); // expected-error{{no member named 'methodd' in 'b6956809_test1::S2'; did you mean 'method'}} expected-error{{no matching member function for call to 'method'}} + } } + +namespace b6956809_test2 { + template<typename T> struct Err { typename T::error n; }; // expected-error{{type 'void *' cannot be used prior to '::' because it has no members}} + struct S { + template<typename T> typename Err<T>::type method(T); // expected-note{{in instantiation of template class 'b6956809_test2::Err<void *>' requested here}} expected-note{{while substituting deduced template arguments into function template 'method' [with T = void *]}} + template<typename T> int method(T *); + }; + + void test() { + S s; + int k = s.methodd((void*)0); // expected-error{{no member named 'methodd' in 'b6956809_test2::S'; did you mean 'method'?}} + } } -struct DataStruct {void foo();}; -struct T { - DataStruct data_struct; - void f(); +// This test should have one correction, followed by an error without a +// suggestion due to exceeding the maximum number of typos for which correction +// is attempted. +namespace CorrectTypo_has_reached_its_limit { +int flibberdy(); // expected-note{{'flibberdy' declared here}} +int no_correction() { + return hibberdy() + // expected-error{{use of undeclared identifier 'hibberdy'; did you mean 'flibberdy'?}} + gibberdy(); // expected-error-re{{use of undeclared identifier 'gibberdy'$}} }; -// should be void T::f(); -void f() { - data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}} } diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index 665cfe7..4991ebe 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -340,7 +340,10 @@ namespace { }; struct E { - int a, b, c; + int b = 1; + int c = 1; + int a; // This field needs to be last to prevent the cross field + // uninitialized warning. E(char (*)[1]) : a(a ? b : c) {} // expected-warning {{field 'a' is uninitialized when used here}} E(char (*)[2]) : a(b ? a : a) {} // expected-warning 2{{field 'a' is uninitialized when used here}} E(char (*)[3]) : a(b ? (a) : c) {} // expected-warning {{field 'a' is uninitialized when used here}} @@ -459,7 +462,7 @@ namespace in_class_initializers { }; struct U { - U() : a(b + 1), b(a + 1) {} // FIXME: Warn here. + U() : a(b + 1), b(a + 1) {} // expected-warning{{field 'b' is uninitialized when used here}} int a = 42; // Note: because a and b are in the member initializer list, these initializers are ignored. int b = 1; }; @@ -484,7 +487,8 @@ namespace references { } struct T { - T() : a(b), b(a) {} // FIXME: Warn here. + T() // expected-note{{during field initialization in this constructor}} + : a(b), b(a) {} // expected-warning{{reference 'b' is not yet bound to a value when used here}} int &a, &b; int &c = c; // expected-warning{{reference 'c' is not yet bound to a value when used here}} }; @@ -523,3 +527,204 @@ namespace lambdas { A a2([&] { return a2.x; }); // ok } } + +namespace record_fields { + struct A { + A() {} + A get(); + static A num(); + static A copy(A); + static A something(A&); + }; + + A ref(A&); + A const_ref(const A&); + A pointer(A*); + A normal(A); + + struct B { + A a; + B(char (*)[1]) : a(a) {} // expected-warning {{uninitialized}} + B(char (*)[2]) : a(a.get()) {} // expected-warning {{uninitialized}} + B(char (*)[3]) : a(a.num()) {} + B(char (*)[4]) : a(a.copy(a)) {} // expected-warning {{uninitialized}} + B(char (*)[5]) : a(a.something(a)) {} + B(char (*)[6]) : a(ref(a)) {} + B(char (*)[7]) : a(const_ref(a)) {} + B(char (*)[8]) : a(pointer(&a)) {} + B(char (*)[9]) : a(normal(a)) {} // expected-warning {{uninitialized}} + }; + struct C { + C() {} // expected-note4{{in this constructor}} + A a1 = a1; // expected-warning {{uninitialized}} + A a2 = a2.get(); // expected-warning {{uninitialized}} + A a3 = a3.num(); + A a4 = a4.copy(a4); // expected-warning {{uninitialized}} + A a5 = a5.something(a5); + A a6 = ref(a6); + A a7 = const_ref(a7); + A a8 = pointer(&a8); + A a9 = normal(a9); // expected-warning {{uninitialized}} + }; + struct D { // expected-note4{{in the implicit default constructor}} + A a1 = a1; // expected-warning {{uninitialized}} + A a2 = a2.get(); // expected-warning {{uninitialized}} + A a3 = a3.num(); + A a4 = a4.copy(a4); // expected-warning {{uninitialized}} + A a5 = a5.something(a5); + A a6 = ref(a6); + A a7 = const_ref(a7); + A a8 = pointer(&a8); + A a9 = normal(a9); // expected-warning {{uninitialized}} + }; + D d; + struct E { + A a1 = a1; + A a2 = a2.get(); + A a3 = a3.num(); + A a4 = a4.copy(a4); + A a5 = a5.something(a5); + A a6 = ref(a6); + A a7 = const_ref(a7); + A a8 = pointer(&a8); + A a9 = normal(a9); + }; +} + +namespace cross_field_warnings { + struct A { + int a, b; + A() {} + A(char (*)[1]) : b(a) {} // expected-warning{{field 'a' is uninitialized when used here}} + A(char (*)[2]) : a(b) {} // expected-warning{{field 'b' is uninitialized when used here}} + }; + + struct B { + int a = b; // expected-warning{{field 'b' is uninitialized when used here}} + int b; + B() {} // expected-note{{during field initialization in this constructor}} + }; + + struct C { + int a; + int b = a; // expected-warning{{field 'a' is uninitialized when used here}} + C(char (*)[1]) : a(5) {} + C(char (*)[2]) {} // expected-note{{during field initialization in this constructor}} + }; + + struct D { + int a; + int &b; + int &c = a; + int d = b; + D() : b(a) {} + }; + + struct E { + int a; + int get(); + static int num(); + E() {} + E(int) {} + }; + + struct F { + int a; + E e; + int b; + F(char (*)[1]) : a(e.get()) {} // expected-warning{{field 'e' is uninitialized when used here}} + F(char (*)[2]) : a(e.num()) {} + F(char (*)[3]) : e(a) {} // expected-warning{{field 'a' is uninitialized when used here}} + F(char (*)[4]) : a(4), e(a) {} + F(char (*)[5]) : e(b) {} // expected-warning{{field 'b' is uninitialized when used here}} + F(char (*)[6]) : e(b), b(4) {} // expected-warning{{field 'b' is uninitialized when used here}} + }; + + struct G { + G(const A&) {}; + }; + + struct H { + A a1; + G g; + A a2; + H() : g(a1) {} + H(int) : g(a2) {} + }; + + struct I { + I(int*) {} + }; + + struct J : public I { + int *a; + int *b; + int c; + J() : I((a = new int(5))), b(a), c(*a) {} + }; + + struct K { + int a = (b = 5); + int b = b + 5; + }; + + struct L { + int a = (b = 5); + int b = b + 5; // expected-warning{{field 'b' is uninitialized when used here}} + L() : a(5) {} // expected-note{{during field initialization in this constructor}} + }; + + struct M { }; + + struct N : public M { + int a; + int b; + N() : b(a) { } // expected-warning{{field 'a' is uninitialized when used here}} + }; + + struct O { + int x = 42; + int get() { return x; } + }; + + struct P { + O o; + int x = o.get(); + P() : x(o.get()) { } + }; + + struct Q { + int a; + int b; + int &c; + Q() : + a(c = 5), // expected-warning{{reference 'c' is not yet bound to a value when used here}} + b(c), // expected-warning{{reference 'c' is not yet bound to a value when used here}} + c(a) {} + }; + + struct R { + int a; + int b; + int c; + int d = a + b + c; + R() : a(c = 5), b(c), c(a) {} + }; +} + +namespace base_class { + struct A { + A (int) {} + }; + + struct B : public A { + int x; + B() : A(x) {} // expected-warning{{field 'x' is uninitialized when used here}} + }; + + struct C : public A { + int x; + int y; + C() : A(y = 4), x(y) {} + }; +} diff --git a/test/SemaCXX/unknown-type-name.cpp b/test/SemaCXX/unknown-type-name.cpp index ce5972b..f2c84df 100644 --- a/test/SemaCXX/unknown-type-name.cpp +++ b/test/SemaCXX/unknown-type-name.cpp @@ -93,14 +93,14 @@ template<typename T> int A<T>::h(T::type x, char) {} // expected-error{{missing template<typename T> int h(T::type, int); // expected-error{{missing 'typename'}} template<typename T> int h(T::type x, char); // expected-error{{missing 'typename'}} -template<typename T> int junk1(T::junk); // expected-error{{declared as a template}} +template<typename T> int junk1(T::junk); // expected-warning{{variable templates are a C++1y extension}} template<typename T> int junk2(T::junk) throw(); // expected-error{{missing 'typename'}} template<typename T> int junk3(T::junk) = delete; // expected-error{{missing 'typename'}} expected-warning{{C++11}} template<typename T> int junk4(T::junk j); // expected-error{{missing 'typename'}} // FIXME: We can tell this was intended to be a function because it does not // have a dependent nested name specifier. -template<typename T> int i(T::type, int()); // expected-error{{variable 'i' declared as a template}} +template<typename T> int i(T::type, int()); // expected-warning{{variable templates are a C++1y extension}} // FIXME: We know which type specifier should have been specified here. Provide // a fix-it to add 'typename A<T>::type' diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp index ebe97f6..24d92f1 100644 --- a/test/SemaCXX/using-decl-1.cpp +++ b/test/SemaCXX/using-decl-1.cpp @@ -118,3 +118,45 @@ namespace foo using ::foo::Class1::Function; // expected-error{{incomplete type 'foo::Class1' named in nested name specifier}} }; } + +// Don't suggest non-typenames for positions requiring typenames. +namespace using_suggestion_tyname_val { +namespace N { void FFF() {} } +using typename N::FFG; // expected-error {{no member named 'FFG' in namespace 'using_suggestion_tyname_val::N'}} +} + +namespace using_suggestion_member_tyname_val { +class CCC { public: void AAA() { } }; +class DDD : public CCC { public: using typename CCC::AAB; }; // expected-error {{no member named 'AAB' in 'using_suggestion_member_tyname_val::CCC'}} +} + +namespace using_suggestion_tyname_val_dropped_specifier { +void FFF() {} +namespace N { } +using typename N::FFG; // expected-error {{no member named 'FFG' in namespace 'using_suggestion_tyname_val_dropped_specifier::N'}} +} + +// Currently hints aren't provided to drop out the incorrect M::. +namespace using_suggestion_ty_dropped_nested_specifier { +namespace N { +class AAA {}; // expected-note {{'N::AAA' declared here}} +namespace M { } +} +using N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_ty_dropped_nested_specifier::N::M'; did you mean 'N::AAA'?}} +} + +namespace using_suggestion_tyname_ty_dropped_nested_specifier { +namespace N { +class AAA {}; // expected-note {{'N::AAA' declared here}} +namespace M { } +} +using typename N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_tyname_ty_dropped_nested_specifier::N::M'; did you mean 'N::AAA'?}} +} + +namespace using_suggestion_val_dropped_nested_specifier { +namespace N { +void FFF() {} // expected-note {{'N::FFF' declared here}} +namespace M { } +} +using N::M::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_nested_specifier::N::M'; did you mean 'N::FFF'?}} +} diff --git a/test/SemaCXX/using-decl-templates.cpp b/test/SemaCXX/using-decl-templates.cpp index 2f8abca..8314688 100644 --- a/test/SemaCXX/using-decl-templates.cpp +++ b/test/SemaCXX/using-decl-templates.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s template<typename T> struct A { void f() { } @@ -80,3 +80,15 @@ namespace PR10883 { void foo(const Container& current); // expected-error {{unknown type name 'Container'}} }; } + +template<typename T> class UsingTypenameNNS { + using typename T::X; + typename X::X x; +}; + +namespace aliastemplateinst { + template<typename T> struct A { }; + template<typename T> using APtr = A<T*>; // expected-note{{previous use is here}} + + template struct APtr<int>; // expected-error{{elaborated type refers to a non-tag type}} +} diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index da06d95..56dafc4 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -17,6 +17,10 @@ void t1() g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} g(10, version); + + void (*ptr)(int, ...) = g; + ptr(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} + ptr(10, version); } void t2() @@ -25,9 +29,17 @@ void t2() c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} c.g(10, version); - + + void (C::*ptr)(int, ...) = &C::g; + (c.*ptr)(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} + (c.*ptr)(10, version); + C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} C::h(10, version); + + void (*static_ptr)(int, ...) = &C::h; + static_ptr(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} + static_ptr(10, version); } int (^block)(int, ...); @@ -141,3 +153,39 @@ namespace t10 { s(f); } } + +namespace t11 { + typedef void(*function_ptr)(int, ...); + typedef void(C::*member_ptr)(int, ...); + typedef void(^block_ptr)(int, ...); + + function_ptr get_f_ptr(); + member_ptr get_m_ptr(); + block_ptr get_b_ptr(); + + function_ptr arr_f_ptr[5]; + member_ptr arr_m_ptr[5]; + block_ptr arr_b_ptr[5]; + + void test() { + C c(10); + + (get_f_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} + (get_f_ptr())(10, version); + + (c.*get_m_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} + (c.*get_m_ptr())(10, version); + + (get_b_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}} + (get_b_ptr())(10, version); + + (arr_f_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} + (arr_f_ptr[3])(10, version); + + (c.*arr_m_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} + (c.*arr_m_ptr[3])(10, version); + + (arr_b_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}} + (arr_b_ptr[3])(10, version); + } +} diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 4d2d064..7957c23 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -37,7 +37,7 @@ void f2_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { } // Test the conditional operator with vector types. -void conditional(bool Cond, char16 c16, longlong16 ll16, char16_e c16e, +void conditional(bool Cond, char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { // Conditional operators with the same type. __typeof__(Cond? c16 : c16) *c16p1 = &c16; @@ -105,11 +105,11 @@ struct convertible_to { // expected-note 3 {{candidate function (the implicit co operator T() const; }; -void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16, +void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e, - convertible_to<char16> to_c16, - convertible_to<longlong16> to_ll16, - convertible_to<char16_e> to_c16e, + convertible_to<char16> to_c16, + convertible_to<longlong16> to_ll16, + convertible_to<char16_e> to_c16e, convertible_to<longlong16_e> to_ll16e, convertible_to<char16&> rto_c16, convertible_to<char16_e&> rto_c16e) { @@ -183,7 +183,7 @@ void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16, (void)(Cond? to_c16 : to_c16e); (void)(Cond? to_ll16e : to_ll16); - + // These 2 are convertable with -flax-vector-conversions (default) (void)(Cond? to_c16 : to_ll16); (void)(Cond? to_c16e : to_ll16e); @@ -278,3 +278,10 @@ void test_pseudo_dtor(fltx4 *f) { (*f).~fltx4(); test_pseudo_dtor_tmpl(f); } + +// PR16204 +typedef __attribute__((ext_vector_type(4))) int vi4; +const int &reference_to_vec_element = vi4(1).x; + +// PR12649 +typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}} diff --git a/test/SemaCXX/virtual-base-used.cpp b/test/SemaCXX/virtual-base-used.cpp index d147b13..04518ce 100644 --- a/test/SemaCXX/virtual-base-used.cpp +++ b/test/SemaCXX/virtual-base-used.cpp @@ -13,19 +13,19 @@ struct D : public virtual B { virtual void foo(); ~D(); }; -void D::foo() { // expected-note {{implicit default destructor for 'B' first required here}} +void D::foo() { // expected-note {{implicit destructor for 'B' first required here}} } struct E : public virtual A { NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}} }; -struct F : public E { // expected-note {{implicit default destructor for 'E' first required here}} +struct F : public E { // expected-note {{implicit destructor for 'E' first required here}} }; struct G : public virtual F { virtual void foo(); ~G(); }; -void G::foo() { // expected-note {{implicit default destructor for 'F' first required here}} +void G::foo() { // expected-note {{implicit destructor for 'F' first required here}} } struct H : public virtual A { @@ -38,5 +38,5 @@ struct J : public I { virtual void foo(); ~J(); }; -void J::foo() { // expected-note {{implicit default destructor for 'H' first required here}} +void J::foo() { // expected-note {{implicit destructor for 'H' first required here}} } diff --git a/test/SemaCXX/virtual-member-functions-key-function.cpp b/test/SemaCXX/virtual-member-functions-key-function.cpp index 09a30b9..80ce029 100644 --- a/test/SemaCXX/virtual-member-functions-key-function.cpp +++ b/test/SemaCXX/virtual-member-functions-key-function.cpp @@ -4,7 +4,7 @@ struct A { }; struct B : A { // expected-error {{no suitable member 'operator delete' in 'B'}} - B() { } // expected-note {{implicit default destructor for 'B' first required here}} + B() { } // expected-note {{implicit destructor for 'B' first required here}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} }; @@ -14,7 +14,7 @@ struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'} void f() { (void)new B; - (void)new C; // expected-note {{implicit default destructor for 'C' first required here}} + (void)new C; // expected-note {{implicit destructor for 'C' first required here}} } // Make sure that the key-function computation is consistent when the diff --git a/test/SemaCXX/virtual-override-x86.cpp b/test/SemaCXX/virtual-override-x86.cpp index ad70d3f..75d8af3 100644 --- a/test/SemaCXX/virtual-override-x86.cpp +++ b/test/SemaCXX/virtual-override-x86.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple=i686-pc-unknown -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -triple=i686-pc-unknown -fsyntax-only -verify %s -std=c++11 -cxx-abi microsoft namespace PR14339 { class A { @@ -28,6 +28,6 @@ namespace PR14339 { class F : public E { public: - void g(); // expected-error{{virtual function 'g' has different calling convention attributes ('void ()') than the function it overrides (which has calling convention 'void () __attribute__((stdcall))'}} + void g(); // expected-error{{virtual function 'g' has different calling convention attributes ('void () __attribute__((thiscall))') than the function it overrides (which has calling convention 'void () __attribute__((stdcall))'}} }; } diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp index a340e9d..6b8231d 100644 --- a/test/SemaCXX/virtuals.cpp +++ b/test/SemaCXX/virtuals.cpp @@ -45,3 +45,9 @@ namespace rdar9670557 { func *h = 0; }; } + +namespace pr8264 { + struct Test { + virtual virtual void func(); // expected-warning {{duplicate 'virtual' declaration specifier}} + }; +} diff --git a/test/SemaCXX/warn-consumed-analysis.cpp b/test/SemaCXX/warn-consumed-analysis.cpp new file mode 100644 index 0000000..64fdc00 --- /dev/null +++ b/test/SemaCXX/warn-consumed-analysis.cpp @@ -0,0 +1,795 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -fcxx-exceptions -std=c++11 %s + +// TODO: Switch to using macros for the expected warnings. + +#define CALLABLE_WHEN(...) __attribute__ ((callable_when(__VA_ARGS__))) +#define CONSUMABLE(state) __attribute__ ((consumable(state))) +#define PARAM_TYPESTATE(state) __attribute__ ((param_typestate(state))) +#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state))) +#define SET_TYPESTATE(state) __attribute__ ((set_typestate(state))) +#define TEST_TYPESTATE(state) __attribute__ ((test_typestate(state))) + +typedef decltype(nullptr) nullptr_t; + +template <typename T> +class CONSUMABLE(unconsumed) ConsumableClass { + T var; + +public: + ConsumableClass(); + ConsumableClass(nullptr_t p) RETURN_TYPESTATE(consumed); + ConsumableClass(T val) RETURN_TYPESTATE(unconsumed); + ConsumableClass(ConsumableClass<T> &other); + ConsumableClass(ConsumableClass<T> &&other); + + ConsumableClass<T>& operator=(ConsumableClass<T> &other); + ConsumableClass<T>& operator=(ConsumableClass<T> &&other); + ConsumableClass<T>& operator=(nullptr_t) SET_TYPESTATE(consumed); + + template <typename U> + ConsumableClass<T>& operator=(ConsumableClass<U> &other); + + template <typename U> + ConsumableClass<T>& operator=(ConsumableClass<U> &&other); + + void operator()(int a) SET_TYPESTATE(consumed); + void operator*() const CALLABLE_WHEN("unconsumed"); + void unconsumedCall() const CALLABLE_WHEN("unconsumed"); + void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown"); + + bool isValid() const TEST_TYPESTATE(unconsumed); + operator bool() const TEST_TYPESTATE(unconsumed); + bool operator!=(nullptr_t) const TEST_TYPESTATE(unconsumed); + bool operator==(nullptr_t) const TEST_TYPESTATE(consumed); + + void constCall() const; + void nonconstCall(); + + void consume() SET_TYPESTATE(consumed); + void unconsume() SET_TYPESTATE(unconsumed); +}; + +class CONSUMABLE(unconsumed) DestructorTester { +public: + DestructorTester() RETURN_TYPESTATE(unconsumed); + DestructorTester(int); + + void operator*() CALLABLE_WHEN("unconsumed"); + + ~DestructorTester() CALLABLE_WHEN("consumed"); +}; + +void baf0(const ConsumableClass<int> var); +void baf1(const ConsumableClass<int> &var); +void baf2(const ConsumableClass<int> *var); + +void baf3(ConsumableClass<int> var); +void baf4(ConsumableClass<int> &var); +void baf5(ConsumableClass<int> *var); +void baf6(ConsumableClass<int> &&var); + +ConsumableClass<int> returnsUnconsumed() { + return ConsumableClass<int>(); // expected-warning {{return value not in expected state; expected 'unconsumed', observed 'consumed'}} +} + +ConsumableClass<int> returnsConsumed() RETURN_TYPESTATE(consumed); +ConsumableClass<int> returnsConsumed() { + return ConsumableClass<int>(); +} + +ConsumableClass<int> returnsUnknown() RETURN_TYPESTATE(unknown); + +void testInitialization() { + ConsumableClass<int> var0; + ConsumableClass<int> var1 = ConsumableClass<int>(); + + var0 = ConsumableClass<int>(); + + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + if (var0.isValid()) { + *var0; + *var1; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + } +} + +void testDestruction() { + DestructorTester D0(42), D1(42); + + *D0; + *D1; + + DestructorTester D2; + *D2; + + D0.~DestructorTester(); // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} + + return; // expected-warning {{invalid invocation of method '~DestructorTester' on object 'D0' while it is in the 'unconsumed' state}} \ + expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} \ + expected-warning {{invalid invocation of method '~DestructorTester' on object 'D2' while it is in the 'unconsumed' state}} +} + +void testTempValue() { + *ConsumableClass<int>(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}} +} + +void testSimpleRValueRefs() { + ConsumableClass<int> var0; + ConsumableClass<int> var1(42); + + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; + + var0 = static_cast<ConsumableClass<int>&&>(var1); + + *var0; + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} +} + +void testIfStmt() { + ConsumableClass<int> var; + + if (var.isValid()) { + *var; + } else { + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + } + + if (!var.isValid()) { + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + } else { + *var; + } + + if (var) { + // Empty + } else { + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + } + + if (var != nullptr) { + // Empty + } else { + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + } + + if (var == nullptr) { + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + } else { + // Empty + } +} + +void testComplexConditionals0() { + ConsumableClass<int> var0, var1, var2; + + if (var0 && var1) { + *var0; + *var1; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + } + + if (var0 || var1) { + *var0; + *var1; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + } + + if (var0 && !var1) { + *var0; + *var1; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + } + + if (var0 || !var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; + *var1; + } + + if (!var0 && !var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; + *var1; + } + + if (!var0 || !var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; + *var1; + } + + if (!(var0 && var1)) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; + *var1; + } + + if (!(var0 || var1)) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; + *var1; + } + + if (var0 && var1 && var2) { + *var0; + *var1; + *var2; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}} + } + +#if 0 + // FIXME: Get this test to pass. + if (var0 || var1 || var2) { + *var0; + *var1; + *var2; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}} + } +#endif +} + +void testComplexConditionals1() { + ConsumableClass<int> var0, var1, var2; + + // Coerce all variables into the unknown state. + baf4(var0); + baf4(var1); + baf4(var2); + + if (var0 && var1) { + *var0; + *var1; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + } + + if (var0 || var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + } + + if (var0 && !var1) { + *var0; + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + } + + if (var0 || !var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; + } + + if (!var0 && !var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + } + + if (!(var0 || var1)) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + } + + if (!var0 || !var1) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + + } else { + *var0; + *var1; + } + + if (!(var0 && var1)) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + + } else { + *var0; + *var1; + } + + if (var0 && var1 && var2) { + *var0; + *var1; + *var2; + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'unknown' state}} + } + +#if 0 + // FIXME: Get this test to pass. + if (var0 || var1 || var2) { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'unknown' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'unknown' state}} + *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'unknown' state}} + + } else { + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + *var2; // expected-warning {{invalid invocation of method 'operator*' on object 'var2' while it is in the 'consumed' state}} + } +#endif +} + +void testStateChangeInBranch() { + ConsumableClass<int> var; + + // Make var enter the 'unknown' state. + baf4(var); + + if (!var) { + var = ConsumableClass<int>(42); + } + + *var; +} + +void testFunctionParam(ConsumableClass<int> param) { + + if (param.isValid()) { + *param; + } else { + *param; + } + + param = nullptr; + *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}} +} + +void testParamReturnTypestateCallee(bool cond, ConsumableClass<int> &Param RETURN_TYPESTATE(unconsumed)) { // expected-warning {{parameter 'Param' not in expected state when the function returns: expected 'unconsumed', observed 'consumed'}} + + if (cond) { + Param.consume(); + return; // expected-warning {{parameter 'Param' not in expected state when the function returns: expected 'unconsumed', observed 'consumed'}} + } + + Param.consume(); +} + +void testParamReturnTypestateCaller() { + ConsumableClass<int> var; + + testParamReturnTypestateCallee(true, var); + + *var; +} + +void testParamTypestateCallee(ConsumableClass<int> Param0 PARAM_TYPESTATE(consumed), + ConsumableClass<int> &Param1 PARAM_TYPESTATE(consumed)) { + + *Param0; // expected-warning {{invalid invocation of method 'operator*' on object 'Param0' while it is in the 'consumed' state}} + *Param1; // expected-warning {{invalid invocation of method 'operator*' on object 'Param1' while it is in the 'consumed' state}} +} + +void testParamTypestateCaller() { + ConsumableClass<int> Var0, Var1(42); + + testParamTypestateCallee(Var0, Var1); // expected-warning {{argument not in expected state; expected 'consumed', observed 'unconsumed'}} +} + +void baf3(ConsumableClass<int> var) { + *var; +} + +void baf4(ConsumableClass<int> &var) { + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} +} + +void baf6(ConsumableClass<int> &&var) { + *var; +} + +void testCallingConventions() { + ConsumableClass<int> var(42); + + baf0(var); + *var; + + baf1(var); + *var; + + baf2(&var); + *var; + + baf4(var); + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} + + var = ConsumableClass<int>(42); + baf5(&var); + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}} + + var = ConsumableClass<int>(42); + baf6(static_cast<ConsumableClass<int>&&>(var)); + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} +} + +void testConstAndNonConstMemberFunctions() { + ConsumableClass<int> var(42); + + var.constCall(); + *var; + + var.nonconstCall(); + *var; +} + +void testFunctionParam0(ConsumableClass<int> param) { + *param; +} + +void testFunctionParam1(ConsumableClass<int> ¶m) { + *param; // expected-warning {{invalid invocation of method 'operator*' on object 'param' while it is in the 'unknown' state}} +} + +void testReturnStates() { + ConsumableClass<int> var; + + var = returnsUnconsumed(); + *var; + + var = returnsConsumed(); + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} +} + +void testCallableWhen() { + ConsumableClass<int> var(42); + + *var; + + baf4(var); + + var.callableWhenUnknown(); +} + +void testMoveAsignmentish() { + ConsumableClass<int> var0; + ConsumableClass<long> var1(42); + + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + *var1; + + var0 = static_cast<ConsumableClass<long>&&>(var1); + + *var0; + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + + var1 = ConsumableClass<long>(42); + var1 = nullptr; + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} +} + +void testConditionalMerge() { + ConsumableClass<int> var; + + if (var.isValid()) { + // Empty + } + + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + + if (var.isValid()) { + // Empty + } else { + // Empty + } + + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} +} + +void testSetTypestate() { + ConsumableClass<int> var(42); + + *var; + + var.consume(); + + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} + + var.unconsume(); + + *var; +} + +void testConsumes0() { + ConsumableClass<int> var(nullptr); + + *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}} +} + +void testConsumes1() { + ConsumableClass<int> var(42); + + var.unconsumedCall(); + var(6); + + var.unconsumedCall(); // expected-warning {{invalid invocation of method 'unconsumedCall' on object 'var' while it is in the 'consumed' state}} +} + +void testUnreachableBlock() { + ConsumableClass<int> var(42); + + if (var) { + *var; + } else { + *var; + } + + *var; +} + + +void testForLoop1() { + ConsumableClass<int> var0, var1(42); + + for (int i = 0; i < 10; ++i) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}} + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + + *var1; + var1.consume(); + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + } + + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} +} + +void testWhileLoop1() { + int i = 10; + + ConsumableClass<int> var0, var1(42); + + while (i-- > 0) { // expected-warning {{state of variable 'var1' must match at the entry and exit of loop}} + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} + + *var1; + var1.consume(); + *var1; // expected-warning {{invalid invocation of method 'operator*' on object 'var1' while it is in the 'consumed' state}} + } + + *var0; // expected-warning {{invalid invocation of method 'operator*' on object 'var0' while it is in the 'consumed' state}} +} + +typedef const int*& IntegerPointerReference; +void testIsRValueRefishAndCanonicalType(IntegerPointerReference a) {} + +namespace ContinueICETest { + +bool cond1(); +bool cond2(); + +static void foo1() { + while (cond1()) { + if (cond2()) + continue; + } +} + +static void foo2() { + while (true) { + if (false) + continue; + } +} + +class runtime_error +{ +public: + virtual ~runtime_error(); +}; + +void read(bool sf) { + while (sf) { + if(sf) throw runtime_error(); + } +} + +} // end namespace ContinueICETest + + +namespace InitializerAssertionFailTest { + +class CONSUMABLE(unconsumed) Status { + int code; + +public: + Status() RETURN_TYPESTATE(consumed); + Status(int c) RETURN_TYPESTATE(unconsumed); + + Status(const Status &other); + Status(Status &&other); + + Status& operator=(const Status &other) CALLABLE_WHEN("unknown", "consumed"); + Status& operator=(Status &&other) CALLABLE_WHEN("unknown", "consumed"); + + bool check() const SET_TYPESTATE(consumed); + void ignore() const SET_TYPESTATE(consumed); + // Status& markAsChecked() { return *this; } + + void clear() CALLABLE_WHEN("unknown", "consumed") SET_TYPESTATE(consumed); + + ~Status() CALLABLE_WHEN("unknown", "consumed"); +}; + + +bool cond(); +Status doSomething(); +void handleStatus(const Status& s RETURN_TYPESTATE(consumed)); +void handleStatusPtr(const Status* s); + +void testSimpleTemporaries0() { + doSomething(); // expected-warning {{invalid invocation of method '~Status' on a temporary object while it is in the 'unconsumed' state}} +} + +void testSimpleTemporaries1() { + doSomething().ignore(); +} + +void testSimpleTemporaries2() { + handleStatus(doSomething()); +} + +void testSimpleTemporaries3() { + Status s = doSomething(); +} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} + +void testSimpleTemporaries4() { + Status s = doSomething(); + s.check(); +} + +void testSimpleTemporaries5() { + Status s = doSomething(); + s.clear(); // expected-warning {{invalid invocation of method 'clear' on object 's' while it is in the 'unconsumed' state}} +} + +void testSimpleTemporaries6() { + Status s = doSomething(); + handleStatus(s); +} + +void testSimpleTemporaries7() { + Status s; + s = doSomething(); +} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} + +void testTemporariesWithConditionals0() { + int a; + + Status s = doSomething(); + if (cond()) a = 0; + else a = 1; +} // expected-warning {{invalid invocation of method '~Status' on object 's' while it is in the 'unconsumed' state}} + +void testTemporariesWithConditionals1() { + int a; + + Status s = doSomething(); + if (cond()) a = 0; + else a = 1; + s.ignore(); +} + +void testTemporariesWithConditionals2() { + int a; + + Status s = doSomething(); + s.ignore(); + if (cond()) a = 0; + else a = 1; +} + +void testTemporariesWithConditionals3() { + Status s = doSomething(); + if (cond()) { + s.check(); + } +} + +void testTemporariesAndConstructors0() { + Status s(doSomething()); + s.check(); +} + +void testTemporariesAndConstructors1() { + // Test the copy constructor. + + Status s1 = doSomething(); + Status s2(s1); + s2.check(); +} // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}} + +void testTemporariesAndConstructors2() { + // Test the move constructor. + + Status s1 = doSomething(); + Status s2(static_cast<Status&&>(s1)); + s2.check(); +} + +void testTemporariesAndOperators0() { + // Test the assignment operator. + + Status s1 = doSomething(); + Status s2; + s2 = s1; + s2.check(); +} // expected-warning {{invalid invocation of method '~Status' on object 's1' while it is in the 'unconsumed' state}} + +void testTemporariesAndOperators1() { + // Test the move assignment operator. + + Status s1 = doSomething(); + Status s2; + s2 = static_cast<Status&&>(s1); + s2.check(); +} + +void testTemporariesAndOperators2() { + Status s1 = doSomething(); + Status s2 = doSomething(); + s1 = s2; // expected-warning {{invalid invocation of method 'operator=' on object 's1' while it is in the 'unconsumed' state}} + s1.check(); + s2.check(); +} + +} // end namespace InitializerAssertionFailTest + diff --git a/test/SemaCXX/warn-consumed-parsing.cpp b/test/SemaCXX/warn-consumed-parsing.cpp new file mode 100644 index 0000000..0a91636 --- /dev/null +++ b/test/SemaCXX/warn-consumed-parsing.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -std=c++11 %s + +#define CALLABLE_WHEN(...) __attribute__ ((callable_when(__VA_ARGS__))) +#define CONSUMABLE(state) __attribute__ ((consumable(state))) +#define SET_TYPESTATE(state) __attribute__ ((set_typestate(state))) +#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state))) +#define TEST_TYPESTATE(state) __attribute__ ((test_typestate(state))) + +// FIXME: This test is here because the warning is issued by the Consumed +// analysis, not SemaDeclAttr. The analysis won't run after an error +// has been issued. Once the attribute propagation for template +// instantiation has been fixed, this can be moved somewhere else and the +// definition can be removed. +int returnTypestateForUnconsumable() RETURN_TYPESTATE(consumed); // expected-warning {{return state set for an unconsumable type 'int'}} +int returnTypestateForUnconsumable() { + return 0; +} + +class AttrTester0 { + void consumes() __attribute__ ((set_typestate())); // expected-error {{attribute takes one argument}} + bool testUnconsumed() __attribute__ ((test_typestate())); // expected-error {{attribute takes one argument}} + void callableWhen() __attribute__ ((callable_when())); // expected-error {{attribute takes at least 1 argument}} +}; + +int var0 SET_TYPESTATE(consumed); // expected-warning {{'set_typestate' attribute only applies to methods}} +int var1 TEST_TYPESTATE(consumed); // expected-warning {{'test_typestate' attribute only applies to methods}} +int var2 CALLABLE_WHEN("consumed"); // expected-warning {{'callable_when' attribute only applies to methods}} +int var3 CONSUMABLE(consumed); // expected-warning {{'consumable' attribute only applies to classes}} +int var4 RETURN_TYPESTATE(consumed); // expected-warning {{'return_typestate' attribute only applies to functions}} + +void function0() SET_TYPESTATE(consumed); // expected-warning {{'set_typestate' attribute only applies to methods}} +void function1() TEST_TYPESTATE(consumed); // expected-warning {{'test_typestate' attribute only applies to methods}} +void function2() CALLABLE_WHEN("consumed"); // expected-warning {{'callable_when' attribute only applies to methods}} +void function3() CONSUMABLE(consumed); // expected-warning {{'consumable' attribute only applies to classes}} + +class CONSUMABLE(unknown) AttrTester1 { + void callableWhen0() CALLABLE_WHEN("unconsumed"); + void callableWhen1() CALLABLE_WHEN(42); // expected-error {{'callable_when' attribute requires a string}} + void callableWhen2() CALLABLE_WHEN("foo"); // expected-warning {{'callable_when' attribute argument not supported: foo}} + void consumes() SET_TYPESTATE(consumed); + bool testUnconsumed() TEST_TYPESTATE(consumed); +}; + +AttrTester1 returnTypestateTester0() RETURN_TYPESTATE(not_a_state); // expected-warning {{'return_typestate' attribute argument not supported: 'not_a_state'}} +AttrTester1 returnTypestateTester1() RETURN_TYPESTATE(42); // expected-error {{'return_typestate' attribute requires an identifier}} + +void returnTypestateTester2(AttrTester1 &Param RETURN_TYPESTATE(unconsumed)); + +class AttrTester2 { + void callableWhen() CALLABLE_WHEN("unconsumed"); // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}} + void consumes() SET_TYPESTATE(consumed); // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}} + bool testUnconsumed() TEST_TYPESTATE(consumed); // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}} +}; + +class CONSUMABLE(42) AttrTester3; // expected-error {{'consumable' attribute requires an identifier}} diff --git a/test/SemaCXX/warn-dangling-field.cpp b/test/SemaCXX/warn-dangling-field.cpp index 95f8c61..eb65bd0 100644 --- a/test/SemaCXX/warn-dangling-field.cpp +++ b/test/SemaCXX/warn-dangling-field.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wdangling-field -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wdangling-field -verify -std=c++11 %s struct X { X(int); @@ -35,3 +35,17 @@ template <typename T> struct S4 { template struct S4<int>; // no warning from this instantiation template struct S4<int&>; // expected-note {{in instantiation}} + +struct S5 { + const X &x; // expected-note {{here}} +}; +S5 s5 = { 0 }; // ok, lifetime-extended + +struct S6 { + S5 s5; // expected-note {{here}} + S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of member 's5' to a temporary}} +}; + +struct S7 : S5 { + S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x' to a temporary}} +}; diff --git a/test/SemaCXX/warn-div-or-rem-by-zero.cpp b/test/SemaCXX/warn-div-or-rem-by-zero.cpp new file mode 100644 index 0000000..44b877e --- /dev/null +++ b/test/SemaCXX/warn-div-or-rem-by-zero.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -std=c++11 -verify %s +// RUN: %clang_cc1 -std=c++1y -verify %s + +void div() { + (void)(42 / 0); // expected-warning{{division by zero is undefined}} + (void)(42 / false); // expected-warning{{division by zero is undefined}} + (void)(42 / !1); // expected-warning{{division by zero is undefined}} + (void)(42 / (1 - 1)); // expected-warning{{division by zero is undefined}} + (void)(42 / !(1 + 1)); // expected-warning{{division by zero is undefined}} + (void)(42 / (int)(0.0)); // expected-warning{{division by zero is undefined}} +} + +void rem() { + (void)(42 % 0); // expected-warning{{remainder by zero is undefined}} + (void)(42 % false); // expected-warning{{remainder by zero is undefined}} + (void)(42 % !1); // expected-warning{{remainder by zero is undefined}} + (void)(42 % (1 - 1)); // expected-warning{{remainder by zero is undefined}} + (void)(42 % !(1 + 1)); // expected-warning{{remainder by zero is undefined}} + (void)(42 % (int)(0.0)); // expected-warning{{remainder by zero is undefined}} +} diff --git a/test/SemaCXX/warn-empty-body.cpp b/test/SemaCXX/warn-empty-body.cpp index d643ced..d3aaac1 100644 --- a/test/SemaCXX/warn-empty-body.cpp +++ b/test/SemaCXX/warn-empty-body.cpp @@ -269,3 +269,8 @@ void test_template_inst(int x) { test_template<double>(x); } +#define IDENTITY(a) a +void test7(int x, int y) { + if (x) IDENTITY(); // no-warning +} + diff --git a/test/SemaCXX/warn-func-not-needed.cpp b/test/SemaCXX/warn-func-not-needed.cpp index d51c173..65721f4 100644 --- a/test/SemaCXX/warn-func-not-needed.cpp +++ b/test/SemaCXX/warn-func-not-needed.cpp @@ -42,3 +42,12 @@ namespace test4 { g<int>(); } } + +namespace test4 { + static void func(); + void bar() { + void func(); + func(); + } + static void func() {} +} diff --git a/test/SemaCXX/warn-global-constructors.cpp b/test/SemaCXX/warn-global-constructors.cpp index 6330958..f57f0de 100644 --- a/test/SemaCXX/warn-global-constructors.cpp +++ b/test/SemaCXX/warn-global-constructors.cpp @@ -95,3 +95,9 @@ namespace pr8095 { static Bar b; } } + +namespace referencemember { + struct A { int &a; }; + int a; + A b = { a }; +} diff --git a/test/SemaCXX/warn-logical-not-compare.cpp b/test/SemaCXX/warn-logical-not-compare.cpp new file mode 100644 index 0000000..3ecce47 --- /dev/null +++ b/test/SemaCXX/warn-logical-not-compare.cpp @@ -0,0 +1,194 @@ +// RUN: %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +bool getBool(); +int getInt(); + +bool test1(int i1, int i2, bool b1, bool b2) { + bool ret; + + ret = !i1 == i2; + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{10:10-10:10}:"(" + // CHECK: fix-it:"{{.*}}":{10:18-10:18}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{10:9-10:9}:"(" + // CHECK: fix-it:"{{.*}}":{10:12-10:12}:")" + + ret = !i1 != i2; + //expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{21:10-21:10}:"(" + // CHECK: fix-it:"{{.*}}":{21:18-21:18}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{21:9-21:9}:"(" + // CHECK: fix-it:"{{.*}}":{21:12-21:12}:")" + + ret = !i1 < i2; + //expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{32:10-32:10}:"(" + // CHECK: fix-it:"{{.*}}":{32:17-32:17}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{32:9-32:9}:"(" + // CHECK: fix-it:"{{.*}}":{32:12-32:12}:")" + + ret = !i1 > i2; + //expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{43:10-43:10}:"(" + // CHECK: fix-it:"{{.*}}":{43:17-43:17}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{43:9-43:9}:"(" + // CHECK: fix-it:"{{.*}}":{43:12-43:12}:")" + + ret = !i1 <= i2; + //expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{54:10-54:10}:"(" + // CHECK: fix-it:"{{.*}}":{54:18-54:18}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{54:9-54:9}:"(" + // CHECK: fix-it:"{{.*}}":{54:12-54:12}:")" + + ret = !i1 >= i2; + //expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{65:10-65:10}:"(" + // CHECK: fix-it:"{{.*}}":{65:18-65:18}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{65:9-65:9}:"(" + // CHECK: fix-it:"{{.*}}":{65:12-65:12}:")" + + ret = i1 == i2; + ret = i1 != i2; + ret = i1 < i2; + ret = i1 > i2; + ret = i1 <= i2; + ret = i1 >= i2; + + // Warning silenced by parens. + ret = (!i1) == i2; + ret = (!i1) != i2; + ret = (!i1) < i2; + ret = (!i1) > i2; + ret = (!i1) <= i2; + ret = (!i1) >= i2; + + ret = !b1 == b2; + ret = !b1 != b2; + ret = !b1 < b2; + ret = !b1 > b2; + ret = !b1 <= b2; + ret = !b1 >= b2; + + ret = !getInt() == i1; + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{98:10-98:10}:"(" + // CHECK: fix-it:"{{.*}}":{98:24-98:24}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{98:9-98:9}:"(" + // CHECK: fix-it:"{{.*}}":{98:18-98:18}:")" + + ret = (!getInt()) == i1; + ret = !getBool() == b1; + return ret; +} + +enum E {e1, e2}; +E getE(); + +bool test2 (E e) { + bool ret; + ret = e == e1; + ret = e == getE(); + ret = getE() == e1; + ret = getE() == getE(); + + ret = !e == e1; + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{124:10-124:10}:"(" + // CHECK: fix-it:"{{.*}}":{124:17-124:17}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{124:9-124:9}:"(" + // CHECK: fix-it:"{{.*}}":{124:11-124:11}:")" + + ret = !e == getE(); + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{135:10-135:10}:"(" + // CHECK: fix-it:"{{.*}}":{135:21-135:21}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{135:9-135:9}:"(" + // CHECK: fix-it:"{{.*}}":{135:11-135:11}:")" + + ret = !getE() == e1; + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{146:10-146:10}:"(" + // CHECK: fix-it:"{{.*}}":{146:22-146:22}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{146:9-146:9}:"(" + // CHECK: fix-it:"{{.*}}":{146:16-146:16}:")" + + ret = !getE() == getE(); + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK: fix-it:"{{.*}}":{157:10-157:10}:"(" + // CHECK: fix-it:"{{.*}}":{157:26-157:26}:")" + // CHECK: to silence this warning + // CHECK: fix-it:"{{.*}}":{157:9-157:9}:"(" + // CHECK: fix-it:"{{.*}}":{157:16-157:16}:")" + + ret = !(e == e1); + ret = !(e == getE()); + ret = !(getE() == e1); + ret = !(getE() == getE()); + + ret = (!e) == e1; + ret = (!e) == getE(); + ret = (!getE()) == e1; + ret = (!getE()) == getE(); + + return ret; +} + +bool PR16673(int x) { + bool ret; + // Make sure we don't emit a fixit for the left paren, but not the right paren. +#define X(x) x + ret = X(!x == 1 && 1); + // expected-warning@-1 {{logical not is only applied to the left hand side of this comparison}} + // expected-note@-2 {{add parentheses after the '!' to evaluate the comparison first}} + // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}} + // CHECK: to evaluate the comparison first + // CHECK-NOT: fix-it + // CHECK: to silence this warning + // CHECK-NOT: fix-it + return ret; +} diff --git a/test/SemaCXX/warn-loop-analysis.cpp b/test/SemaCXX/warn-loop-analysis.cpp index 627bc51..c666c48 100644 --- a/test/SemaCXX/warn-loop-analysis.cpp +++ b/test/SemaCXX/warn-loop-analysis.cpp @@ -152,3 +152,111 @@ void test6() { for (;x6;); for (;y;); } + +void test7() { + int i; + for (;;i++) { // expected-note{{incremented here}} + if (true) test7(); + i++; // expected-warning{{incremented both}} + } + for (;;i++) { // expected-note{{incremented here}} + if (true) break; + ++i; // expected-warning{{incremented both}} + } + for (;;++i) { // expected-note{{incremented here}} + while (true) return; + i++; // expected-warning{{incremented both}} + } + for (;;++i) { // expected-note{{incremented here}} + ++i; // expected-warning{{incremented both}} + } + + for (;;i--) { // expected-note{{decremented here}} + if (true) test7(); + i--; // expected-warning{{decremented both}} + } + for (;;i--) { // expected-note{{decremented here}} + if (true) break; + --i; // expected-warning{{decremented both}} + } + for (;;--i) { // expected-note{{decremented here}} + while (true) return; + i--; // expected-warning{{decremented both}} + } + for (;;--i) { // expected-note{{decremented here}} + --i; // expected-warning{{decremented both}} + } + + // Don't warn when loop is only one statement. + for (;;++i) + i++; + for (;;--i) + --i; + + // Don't warn when loop has continue statement. + for (;;i++) { + if (true) continue; + i++; + } + for (;;i--) { + if (true) continue; + i--; + } +} + +struct iterator { + iterator operator++() { return *this; } + iterator operator++(int) { return *this; } + iterator operator--() { return *this; } + iterator operator--(int) { return *this; } +}; +void test8() { + iterator i; + for (;;i++) { // expected-note{{incremented here}} + if (true) test7(); + i++; // expected-warning{{incremented both}} + } + for (;;i++) { // expected-note{{incremented here}} + if (true) break; + ++i; // expected-warning{{incremented both}} + } + for (;;++i) { // expected-note{{incremented here}} + while (true) return; + i++; // expected-warning{{incremented both}} + } + for (;;++i) { // expected-note{{incremented here}} + ++i; // expected-warning{{incremented both}} + } + + for (;;i--) { // expected-note{{decremented here}} + if (true) test7(); + i--; // expected-warning{{decremented both}} + } + for (;;i--) { // expected-note{{decremented here}} + if (true) break; + --i; // expected-warning{{decremented both}} + } + for (;;--i) { // expected-note{{decremented here}} + while (true) return; + i--; // expected-warning{{decremented both}} + } + for (;;--i) { // expected-note{{decremented here}} + --i; // expected-warning{{decremented both}} + } + + // Don't warn when loop is only one statement. + for (;;++i) + i++; + for (;;--i) + --i; + + // Don't warn when loop has continue statement. + for (;;i++) { + if (true) continue; + i++; + } + for (;;i--) { + if (true) continue; + i--; + } +} diff --git a/test/SemaCXX/warn-member-not-needed.cpp b/test/SemaCXX/warn-member-not-needed.cpp new file mode 100644 index 0000000..61bb348 --- /dev/null +++ b/test/SemaCXX/warn-member-not-needed.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wunneeded-member-function %s + +namespace { + class A { + void g() {} // expected-warning {{is not needed and will not be emitted}} + template <typename T> + void foo() { + g(); + } + }; +} diff --git a/test/SemaCXX/warn-missing-variable-declarations.cpp b/test/SemaCXX/warn-missing-variable-declarations.cpp index 12af973..ad23e04 100644 --- a/test/SemaCXX/warn-missing-variable-declarations.cpp +++ b/test/SemaCXX/warn-missing-variable-declarations.cpp @@ -41,3 +41,9 @@ int CGood1::MGood1; namespace { int mgood4; } + +class C { + void test() { + static int x = 0; // no-warn + } +}; diff --git a/test/SemaCXX/warn-reinterpret-base-class.cpp b/test/SemaCXX/warn-reinterpret-base-class.cpp index 67902f7..36b8fda 100644 --- a/test/SemaCXX/warn-reinterpret-base-class.cpp +++ b/test/SemaCXX/warn-reinterpret-base-class.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -std=c++11 -fsyntax-only -fdiagnostics-parseable-fixits -Wreinterpret-base-class -Wno-unused-volatile-lvalue %s 2>&1 | FileCheck %s // PR 13824 class A { diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index bc4b40e..ce6250d 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -11,8 +11,10 @@ #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_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__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__))) @@ -33,6 +35,9 @@ class __attribute__((lockable)) Mutex { bool TryLock() __attribute__((exclusive_trylock_function(true))); bool ReaderTryLock() __attribute__((shared_trylock_function(true))); void LockWhen(const int &cond) __attribute__((exclusive_lock_function)); + + void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); + void AssertReaderHeld() ASSERT_SHARED_LOCK(); }; class __attribute__((scoped_lockable)) MutexLock { @@ -75,6 +80,7 @@ public: T* get() const { return ptr_; } T* operator->() const { return ptr_; } T& operator*() const { return *ptr_; } + T& operator[](int i) const { return ptr_[i]; } private: T* ptr_; @@ -102,14 +108,14 @@ class MutexWrapper { public: Mutex mu; int x __attribute__((guarded_by(mu))); - void MyLock() __attribute__((exclusive_lock_function(mu))); + void MyLock() __attribute__((exclusive_lock_function(mu))); }; MutexWrapper sls_mw; void sls_fun_0() { sls_mw.mu.Lock(); - sls_mw.x = 5; + sls_mw.x = 5; sls_mw.mu.Unlock(); } @@ -3069,44 +3075,6 @@ void Foo::test1() { #endif } - -void Foo::test2() { -/* FIXME: these tests depend on changes to the CFG. - * - if (mu_.TryLock() && c) { - a = 0; - unlock(); - } - else return; - - if (c && mu_.TryLock()) { - a = 0; - unlock(); - } - else return; - - if (!(mu_.TryLock() && c)) - return; - a = 0; - unlock(); - - if (!(c && mu_.TryLock())) - return; - a = 0; - unlock(); - - if (!(mu_.TryLock() == 0) && c) { - a = 0; - unlock(); - } - - if (!mu_.TryLock() || c) - return; - a = 0; - unlock(); -*/ -} - } // end namespace TryLockEqTest @@ -3985,3 +3953,364 @@ private: } // end namespace LockUnlockFunctionTest + +namespace AssertHeldTest { + +class Foo { +public: + int c; + int a GUARDED_BY(mu_); + Mutex mu_; + + void test1() { + mu_.AssertHeld(); + int b = a; + a = 0; + } + + void test2() { + mu_.AssertReaderHeld(); + int b = a; + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}} + } + + void test3() { + if (c) { + mu_.AssertHeld(); + } + else { + mu_.AssertHeld(); + } + int b = a; + a = 0; + } + + void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) { + mu_.AssertHeld(); + int b = a; + a = 0; + } + + void test5() UNLOCK_FUNCTION(mu_) { + mu_.AssertHeld(); + mu_.Unlock(); + } + + void test6() { + mu_.AssertHeld(); + mu_.Unlock(); + } // should this be a warning? + + void test7() { + if (c) { + mu_.AssertHeld(); + } + else { + mu_.Lock(); + } + int b = a; + a = 0; + mu_.Unlock(); + } + + void test8() { + if (c) { + mu_.Lock(); + } + else { + mu_.AssertHeld(); + } + int b = a; + a = 0; + mu_.Unlock(); + } + + void test9() { + if (c) { + mu_.AssertHeld(); + } + else { + mu_.Lock(); // expected-note {{mutex acquired here}} + } + } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + + void test10() { + if (c) { + mu_.Lock(); // expected-note {{mutex acquired here}} + } + else { + mu_.AssertHeld(); + } + } // expected-warning {{mutex 'mu_' is still locked at the end of function}} + + void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_); + + void test11() { + assertMu(); + int b = a; + a = 0; + } +}; + +} // end namespace AssertHeldTest + + +namespace LogicalConditionalTryLock { + +class Foo { +public: + Mutex mu; + int a GUARDED_BY(mu); + bool c; + + bool newc(); + + void test1() { + if (c && mu.TryLock()) { + a = 0; + mu.Unlock(); + } + } + + void test2() { + bool b = mu.TryLock(); + if (c && b) { + a = 0; + mu.Unlock(); + } + } + + void test3() { + if (c || !mu.TryLock()) + return; + a = 0; + mu.Unlock(); + } + + void test4() { + while (c && mu.TryLock()) { + a = 0; + c = newc(); + mu.Unlock(); + } + } + + void test5() { + while (c) { + if (newc() || !mu.TryLock()) + break; + a = 0; + mu.Unlock(); + } + } + + void test6() { + mu.Lock(); + do { + a = 0; + mu.Unlock(); + } while (newc() && mu.TryLock()); + } + + void test7() { + for (bool b = mu.TryLock(); c && b;) { + a = 0; + mu.Unlock(); + } + } + + void test8() { + if (c && newc() && mu.TryLock()) { + a = 0; + mu.Unlock(); + } + } + + void test9() { + if (!(c && newc() && mu.TryLock())) + return; + a = 0; + mu.Unlock(); + } + + void test10() { + if (!(c || !mu.TryLock())) { + a = 0; + mu.Unlock(); + } + } +}; + +} // end namespace LogicalConditionalTryLock + + + +namespace PtGuardedByTest { + +void doSomething(); + +class Cell { + public: + int a; +}; + + +// This mainly duplicates earlier tests, but just to make sure... +class PtGuardedBySanityTest { + Mutex mu1; + Mutex mu2; + int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + int sa[10] GUARDED_BY(mu1); + Cell sc[10] GUARDED_BY(mu1); + + void test1() { + mu1.Lock(); + if (a == 0) doSomething(); // OK, we don't dereference. + a = 0; + c = 0; + if (sa[0] == 42) doSomething(); + sa[0] = 57; + if (sc[0].a == 42) doSomething(); + sc[0].a = 57; + mu1.Unlock(); + } + + void test2() { + mu1.ReaderLock(); + if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires locking 'mu2'}} + *a = 0; // expected-warning {{writing the value pointed to by 'a' requires locking 'mu2' exclusively}} + + if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} + c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + + if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} + (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + + if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires locking 'mu2'}} + a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires locking 'mu2' exclusively}} + if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} + c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + mu1.Unlock(); + } + + void test3() { + mu2.Lock(); + if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires locking 'mu1'}} + *a = 0; // expected-warning {{reading variable 'a' requires locking 'mu1'}} + + if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} + c->a = 0; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + + if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} + (*c).a = 0; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + + if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires locking 'mu1'}} + a[0] = 57; // expected-warning {{reading variable 'a' requires locking 'mu1'}} + if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} + c[0].a = 57; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + mu2.Unlock(); + } + + void test4() { // Literal arrays + if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires locking 'mu1'}} + sa[0] = 57; // expected-warning {{writing variable 'sa' requires locking 'mu1' exclusively}} + if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires locking 'mu1'}} + sc[0].a = 57; // expected-warning {{writing variable 'sc' requires locking 'mu1' exclusively}} + + if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires locking 'mu1'}} + *sa = 57; // expected-warning {{writing variable 'sa' requires locking 'mu1' exclusively}} + if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires locking 'mu1'}} + (*sc).a = 57; // expected-warning {{writing variable 'sc' requires locking 'mu1' exclusively}} + if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires locking 'mu1'}} + sc->a = 57; // expected-warning {{writing variable 'sc' requires locking 'mu1' exclusively}} + } + + void test5() { + mu1.ReaderLock(); // OK -- correct use. + mu2.Lock(); + if (*a == 0) doSomething(); + *a = 0; + + if (c->a == 0) doSomething(); + c->a = 0; + + if ((*c).a == 0) doSomething(); + (*c).a = 0; + mu2.Unlock(); + mu1.Unlock(); + } +}; + + +class SmartPtr_PtGuardedBy_Test { + Mutex mu1; + Mutex mu2; + SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + + void test1() { + mu1.ReaderLock(); + mu2.Lock(); + + sp.get(); + if (*sp == 0) doSomething(); + *sp = 0; + sq->a = 0; + + if (sp[0] == 0) doSomething(); + sp[0] = 0; + + mu2.Unlock(); + mu1.Unlock(); + } + + void test2() { + mu2.Lock(); + + sp.get(); // expected-warning {{reading variable 'sp' requires locking 'mu1'}} + if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires locking 'mu1'}} + *sp = 0; // expected-warning {{reading variable 'sp' requires locking 'mu1'}} + sq->a = 0; // expected-warning {{reading variable 'sq' requires locking 'mu1'}} + + if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires locking 'mu1'}} + sp[0] = 0; // expected-warning {{reading variable 'sp' requires locking 'mu1'}} + if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires locking 'mu1'}} + sq[0].a = 0; // expected-warning {{reading variable 'sq' requires locking 'mu1'}} + + mu2.Unlock(); + } + + void test3() { + mu1.Lock(); + + sp.get(); + if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} + *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} + sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} + + if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} + sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} + if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} + sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} + + mu1.Unlock(); + } +}; + +} // end namespace PtGuardedByTest + + +namespace NonMemberCalleeICETest { + +class A { + void Run() { + (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires exclusive lock on 'M'}} + } + + void RunHelper() __attribute__((exclusive_locks_required(M))); + Mutex M; +}; + +} // end namespace NonMemberCalleeICETest + diff --git a/test/SemaCXX/warn-thread-safety-parsing.cpp b/test/SemaCXX/warn-thread-safety-parsing.cpp index df9415c..1bd4e43 100644 --- a/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -8,8 +8,10 @@ #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_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__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__))) @@ -24,7 +26,15 @@ class LOCKABLE Mutex { public: - void Lock(); + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void ReaderLock() SHARED_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); + + bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); + bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); + + void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); + void AssertReaderHeld() ASSERT_SHARED_LOCK(); }; class UnlockableMu{ @@ -93,7 +103,7 @@ class Bar { void noanal_fun() NO_THREAD_SAFETY_ANALYSIS; void noanal_fun_args() __attribute__((no_thread_safety_analysis(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'no_thread_safety_analysis' attribute takes no arguments}} int noanal_testfn(int y) NO_THREAD_SAFETY_ANALYSIS; @@ -132,13 +142,13 @@ void noanal_fun_params(int lvar NO_THREAD_SAFETY_ANALYSIS); // \ int gv_var_noargs GUARDED_VAR; int gv_var_args __attribute__((guarded_var(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'guarded_var' attribute takes no arguments}} class GVFoo { private: int gv_field_noargs GUARDED_VAR; int gv_field_args __attribute__((guarded_var(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'guarded_var' attribute takes no arguments}} }; class GUARDED_VAR GV { // \ @@ -178,7 +188,7 @@ class PGVFoo { int field_noargs PT_GUARDED_VAR; // \ // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} int *gv_field_args __attribute__((pt_guarded_var(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'pt_guarded_var' attribute takes no arguments}} }; class PT_GUARDED_VAR PGV { // \ @@ -186,7 +196,7 @@ class PT_GUARDED_VAR PGV { // \ }; int *pgv_var_args __attribute__((pt_guarded_var(1))); // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'pt_guarded_var' attribute takes no arguments}} void pgv_function() PT_GUARDED_VAR; // \ @@ -215,7 +225,7 @@ class LOCKABLE LTestClass { }; class __attribute__((lockable (1))) LTestClass_args { // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'lockable' attribute takes no arguments}} }; void l_test_function() LOCKABLE; // \ @@ -255,7 +265,7 @@ class SCOPED_LOCKABLE SLTestClass { }; class __attribute__((scoped_lockable (1))) SLTestClass_args { // \ - // expected-error {{attribute takes no arguments}} + // expected-error {{'scoped_lockable' attribute takes no arguments}} }; void sl_test_function() SCOPED_LOCKABLE; // \ @@ -297,16 +307,18 @@ void sl_function_params(int lvar SCOPED_LOCKABLE); // \ int gb_var_arg GUARDED_BY(mu1); +int gb_non_ascii GUARDED_BY(L"wide"); // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} + int gb_var_args __attribute__((guarded_by(mu1, mu2))); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'guarded_by' attribute takes one argument}} int gb_var_noargs __attribute__((guarded_by)); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'guarded_by' attribute takes one argument}} class GBFoo { private: int gb_field_noargs __attribute__((guarded_by)); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'guarded_by' attribute takes one argument}} int gb_field_args GUARDED_BY(mu1); }; @@ -364,12 +376,12 @@ int gb_var_arg_bad_4 GUARDED_BY(umu); // \ //1. Check applied to the right types & argument number int *pgb_var_noargs __attribute__((pt_guarded_by)); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'pt_guarded_by' attribute takes one argument}} int *pgb_ptr_var_arg PT_GUARDED_BY(mu1); int *pgb_ptr_var_args __attribute__((pt_guarded_by(mu1, mu2))); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'pt_guarded_by' attribute takes one argument}} int pgb_var_args PT_GUARDED_BY(mu1); // \ // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}} @@ -377,7 +389,7 @@ int pgb_var_args PT_GUARDED_BY(mu1); // \ class PGBFoo { private: int *pgb_field_noargs __attribute__((pt_guarded_by)); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'pt_guarded_by' attribute takes one argument}} int *pgb_field_args PT_GUARDED_BY(mu1); }; @@ -750,11 +762,11 @@ int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); // illegal attribute arguments int etf_function_bad_1() EXCLUSIVE_TRYLOCK_FUNCTION(mu1); // \ - // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} + // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} int etf_function_bad_2() EXCLUSIVE_TRYLOCK_FUNCTION("mu"); // \ - // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} + // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} int etf_function_bad_3() EXCLUSIVE_TRYLOCK_FUNCTION(muDoublePointer); // \ - // expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}} + // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} int etf_function_bad_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, "mu"); // \ // expected-warning {{ignoring 'exclusive_trylock_function' attribute because its argument is invalid}} @@ -824,11 +836,11 @@ int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); // illegal attribute arguments int stf_function_bad_1() SHARED_TRYLOCK_FUNCTION(mu1); // \ - // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} + // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} int stf_function_bad_2() SHARED_TRYLOCK_FUNCTION("mu"); // \ - // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} + // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} int stf_function_bad_3() SHARED_TRYLOCK_FUNCTION(muDoublePointer); // \ - // expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}} + // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} int stf_function_bad_4() SHARED_TRYLOCK_FUNCTION(1, "mu"); // \ // expected-warning {{ignoring 'shared_trylock_function' attribute because its argument is invalid}} @@ -921,12 +933,12 @@ int uf_function_bad_7() UNLOCK_FUNCTION(0); // \ // Takes exactly one argument, a var/field void lr_function() __attribute__((lock_returned)); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'lock_returned' attribute takes one argument}} void lr_function_arg() LOCK_RETURNED(mu1); void lr_function_args() __attribute__((lock_returned(mu1, mu2))); // \ - // expected-error {{attribute takes one argument}} + // expected-error {{'lock_returned' attribute takes one argument}} int lr_testfn(int y) LOCK_RETURNED(mu1); diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index f36300a..dd07125 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -62,8 +62,8 @@ void test5() { struct S { int mem; } s; - S &foor() __attribute__((noreturn)); - foor() + S &foonr() __attribute__((noreturn)); + foonr() .mem; // expected-warning {{will never be executed}} } diff --git a/test/SemaCXX/warn-unsequenced.cpp b/test/SemaCXX/warn-unsequenced.cpp index c7acfca..54e16a5 100644 --- a/test/SemaCXX/warn-unsequenced.cpp +++ b/test/SemaCXX/warn-unsequenced.cpp @@ -1,12 +1,13 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-unused %s -int f(int, int); +int f(int, int = 0); struct A { int x, y; }; struct S { S(int, int); + int n; }; void test() { @@ -32,6 +33,9 @@ void test() { f(a = 0, a); // expected-warning {{unsequenced modification and access}} f(a, a += 0); // expected-warning {{unsequenced modification and access}} f(a = 0, a = 0); // expected-warning {{multiple unsequenced modifications}} + a = f(++a); // ok + a = f(a++); // ok + a = f(++a, a++); // expected-warning {{multiple unsequenced modifications}} // Compound assignment "A OP= B" is equivalent to "A = A OP B" except that A // is evaluated only once. @@ -47,6 +51,12 @@ void test() { S str2 = { a++, a++ }; // ok S str3 = { a++ + a, a++ }; // expected-warning {{unsequenced modification and access}} + struct Z { A a; S s; } z = { { ++a, ++a }, { ++a, ++a } }; // ok + a = S { ++a, a++ }.n; // ok + A { ++a, a++ }.x; // ok + a = A { ++a, a++ }.x; // expected-warning {{unsequenced modifications}} + A { ++a, a++ }.x + A { ++a, a++ }.y; // expected-warning {{unsequenced modifications}} + (xs[2] && (a = 0)) + a; // ok (0 && (a = 0)) + a; // ok (1 && (a = 0)) + a; // expected-warning {{unsequenced modification and access}} @@ -58,6 +68,8 @@ void test() { (xs[4] ? a : ++a) + a; // ok (0 ? a : ++a) + a; // expected-warning {{unsequenced modification and access}} (1 ? a : ++a) + a; // ok + (0 ? a : a++) + a; // expected-warning {{unsequenced modification and access}} + (1 ? a : a++) + a; // ok (xs[5] ? ++a : ++a) + a; // FIXME: warn here (++a, xs[6] ? ++a : 0) + a; // expected-warning {{unsequenced modification and access}} diff --git a/test/SemaCXX/warn-unused-attribute.cpp b/test/SemaCXX/warn-unused-attribute.cpp new file mode 100644 index 0000000..72f96ee --- /dev/null +++ b/test/SemaCXX/warn-unused-attribute.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s +struct __attribute__((warn_unused)) Test +{ + Test(); + ~Test(); + void use(); +}; + +struct TestNormal +{ + TestNormal(); +}; + +int main() +{ + Test unused; // expected-warning {{unused variable 'unused'}} + Test used; + TestNormal normal; + used.use(); +} diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp index 9fb6011..b0af5b3 100644 --- a/test/SemaCXX/warn-unused-filescoped.cpp +++ b/test/SemaCXX/warn-unused-filescoped.cpp @@ -1,6 +1,41 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-c++11-extensions -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -std=c++11 %s +#ifdef HEADER + +static void headerstatic() {} // expected-warning{{unused}} +static inline void headerstaticinline() {} + +namespace { + void headeranon() {} // expected-warning{{unused}} + inline void headerinlineanon() {} +} + +namespace test7 +{ + template<typename T> + static inline void foo(T) { } + + // This should not emit an unused-function warning since it inherits + // the static storage type from the base template. + template<> + inline void foo(int) { } + + // Partial specialization + template<typename T, typename U> + static inline void bar(T, U) { } + + template<typename U> + inline void bar(int, U) { } + + template<> + inline void bar(int, int) { } +}; + +#else +#define HEADER +#include "warn-unused-filescoped.cpp" + static void f1(); // expected-warning{{unused}} namespace { @@ -37,8 +72,10 @@ namespace { void S::m3() { } // expected-warning{{unused}} -static inline void f4() { } -const unsigned int cx = 0; +static inline void f4() { } // expected-warning{{unused}} +const unsigned int cx = 0; // expected-warning{{unused}} +const unsigned int cy = 0; +int f5() { return cy; } static int x1; // expected-warning{{unused}} @@ -98,7 +135,7 @@ namespace test5 { // FIXME: We should produce warnings for both of these. static const int m = n; int x = sizeof(m); - static const double d = 0.0; + static const double d = 0.0; // expected-warning{{not needed and will not be emitted}} int y = sizeof(d); } @@ -133,27 +170,6 @@ namespace test6 { }; } -namespace test7 -{ - template<typename T> - static inline void foo(T) { } - - // This should not emit an unused-function warning since it inherits - // the static storage type from the base template. - template<> - inline void foo(int) { } - - // Partial specialization - template<typename T, typename U> - static inline void bar(T, U) { } - - template<typename U> - inline void bar(int, U) { } - - template<> - inline void bar(int, int) { } -}; - namespace pr14776 { namespace { struct X {}; @@ -161,3 +177,20 @@ namespace pr14776 { X a = X(); // expected-warning {{unused variable 'a'}} auto b = X(); // expected-warning {{unused variable 'b'}} } + +namespace UndefinedInternalStaticMember { + namespace { + struct X { + static const unsigned x = 3; + int y[x]; + }; + } +} + +namespace test8 { +static void func(); +void bar() { void func() __attribute__((used)); } +static void func() {} +} + +#endif diff --git a/test/SemaCXX/warn-unused-private-field.cpp b/test/SemaCXX/warn-unused-private-field.cpp index 661442d..932a7dc 100644 --- a/test/SemaCXX/warn-unused-private-field.cpp +++ b/test/SemaCXX/warn-unused-private-field.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++11 %s class NotFullyDefined { public: diff --git a/test/SemaCXX/warn-unused-result.cpp b/test/SemaCXX/warn-unused-result.cpp index b0bf61f..581af09 100644 --- a/test/SemaCXX/warn-unused-result.cpp +++ b/test/SemaCXX/warn-unused-result.cpp @@ -78,3 +78,19 @@ void lazy() { DoYetAnotherThing(); } } + +namespace PR17587 { +struct [[clang::warn_unused_result]] Status; + +struct Foo { + Status Bar(); +}; + +struct Status {}; + +void Bar() { + Foo f; + f.Bar(); // expected-warning {{ignoring return value}} +}; + +} diff --git a/test/SemaCXX/warn-unused-value.cpp b/test/SemaCXX/warn-unused-value.cpp index 072ee60..5e43d3e 100644 --- a/test/SemaCXX/warn-unused-value.cpp +++ b/test/SemaCXX/warn-unused-value.cpp @@ -49,3 +49,23 @@ namespace test2 { } } +namespace test3 { +struct Used { + Used(); + Used(int); + Used(int, int); +}; +struct __attribute__((warn_unused)) Unused { + Unused(); + Unused(int); + Unused(int, int); +}; +void f() { + Used(); + Used(1); + Used(1, 1); + Unused(); // expected-warning {{expression result unused}} + Unused(1); // expected-warning {{expression result unused}} + Unused(1, 1); // expected-warning {{expression result unused}} +} +} diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 00597f9..93d2f6f 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -verify %s template<typename T> void f() { T t; t = 17; @@ -128,3 +128,26 @@ namespace ctor_with_cleanups { } #include "Inputs/warn-unused-variables.h" + +namespace PR8455 { + void f() { + A: // expected-warning {{unused label 'A'}} + __attribute__((unused)) int i; // attribute applies to variable + B: // attribute applies to label + __attribute__((unused)); int j; // expected-warning {{unused variable 'j'}} + } + + void g() { + C: // unused label 'C' will not appear here because an error occurs + __attribute__((unused)) + #pragma weak unused_local_static // expected-error {{expected ';' after __attribute__}} + ; + } + + void h() { + D: // expected-warning {{unused label 'D'}} + #pragma weak unused_local_static + __attribute__((unused)) // expected-warning {{declaration does not declare anything}} + ; + } +} diff --git a/test/SemaCXX/warn-using-namespace-in-header.cpp b/test/SemaCXX/warn-using-namespace-in-header.cpp index f68b998..6b84e6e 100644 --- a/test/SemaCXX/warn-using-namespace-in-header.cpp +++ b/test/SemaCXX/warn-using-namespace-in-header.cpp @@ -57,4 +57,13 @@ using namespace dont_warn; // cc file. USING_MACRO +// Check behavior of line markers. +namespace warn_header_with_line_marker {} +# 1 "XXX.h" 1 +using namespace warn_header_with_line_marker; // expected-warning {{using namespace directive in global context in header}} +# 70 "warn-using-namespace-in-header.cpp" 2 + +namespace nowarn_after_line_marker {} +using namespace nowarn_after_line_marker; + #endif diff --git a/test/SemaCXX/writable-strings-deprecated.cpp b/test/SemaCXX/writable-strings-deprecated.cpp index 8295401..b8f605b 100644 --- a/test/SemaCXX/writable-strings-deprecated.cpp +++ b/test/SemaCXX/writable-strings-deprecated.cpp @@ -1,11 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -Wno-deprecated-writable-strings -verify %s // RUN: %clang_cc1 -fsyntax-only -fwritable-strings -verify %s // RUN: %clang_cc1 -fsyntax-only -Wno-write-strings -verify %s +// RUN: %clang_cc1 -fsyntax-only -Werror=c++11-compat -verify %s -DERROR // rdar://8827606 char *fun(void) { return "foo"; +#ifdef ERROR + // expected-error@-2 {{deprecated}} +#endif } void test(bool b) |