diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
commit | 180abc3db9ae3b4fc63cd65b15697e6ffcc8a657 (patch) | |
tree | 2097d084eb235c0b12c0bff3445f4ec7bbaa8a12 /test/SemaCXX | |
parent | 29cafa66ad3878dbb9f82615f19fa0bded2e443c (diff) |
Notes
Diffstat (limited to 'test/SemaCXX')
33 files changed, 781 insertions, 30 deletions
diff --git a/test/SemaCXX/PR10243.cpp b/test/SemaCXX/PR10243.cpp new file mode 100644 index 0000000000000..9a58510498031 --- /dev/null +++ b/test/SemaCXX/PR10243.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +struct S; // expected-note 4{{forward declaration of 'S'}} + +struct T0 { + S s; // expected-error{{field has incomplete type 'S'}} + T0() = default; +}; + +struct T1 { + S s; // expected-error{{field has incomplete type 'S'}} + T1(T1&) = default; +}; + +struct T2 { + S s; // expected-error{{field has incomplete type 'S'}} + T2& operator=(T2&) = default; +}; + +struct T3 { + S s; // expected-error{{field has incomplete type 'S'}} + ~T3() = default; +}; diff --git a/test/SemaCXX/PR7410.cpp b/test/SemaCXX/PR7410.cpp new file mode 100644 index 0000000000000..6d2cda90b1d33 --- /dev/null +++ b/test/SemaCXX/PR7410.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct BaseReturn {}; + +struct Base { + virtual BaseReturn Foo() = 0; // expected-note{{overridden virtual function is here}} +}; +struct X {}; +struct Derived : Base { + X Foo(); // expected-error{{virtual function 'Foo' has a different return type ('X') than the function it overrides (which has return type 'BaseReturn')}} +}; + +Derived d; diff --git a/test/SemaCXX/PR9459.cpp b/test/SemaCXX/PR9459.cpp index dfb242dc59524..2b96f34e8a72a 100644 --- a/test/SemaCXX/PR9459.cpp +++ b/test/SemaCXX/PR9459.cpp @@ -3,5 +3,5 @@ // Don't crash. template<typename>struct ae_same; -template<typename>struct ts{}ap() +template<typename>struct ts{}ap() // expected-error {{expected ';' after struct}} expected-error {{requires a type specifier}} {ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error {{use of undeclared identifier 'a'}} diff --git a/test/SemaCXX/alignof-sizeof-reference.cpp b/test/SemaCXX/alignof-sizeof-reference.cpp index b517e43cf1ffd..93ba203ae112e 100644 --- a/test/SemaCXX/alignof-sizeof-reference.cpp +++ b/test/SemaCXX/alignof-sizeof-reference.cpp @@ -13,3 +13,9 @@ void f(int); // expected-note{{candidate function}} void g() { sizeof(&f); // expected-error{{cannot resolve overloaded function 'f' from context}} } + +template<typename T> void f_template(); // expected-note{{candidate function}} +template<typename T> void f_template(T*); // expected-note{{candidate function}} +void rdar9659191() { + (void)alignof(f_template<int>); // expected-error{{cannot resolve overloaded function 'f_template' from context}} +} diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp index 5f34ed9904135..2d82668a205a3 100644 --- a/test/SemaCXX/attr-unavailable.cpp +++ b/test/SemaCXX/attr-unavailable.cpp @@ -28,3 +28,12 @@ void bar() { foo(); // expected-error {{call to unavailable function 'foo': not available - replaced}} } } + +void unavail(short* sp) __attribute__((__unavailable__)); +void unavail(short* sp) { + // No complains inside an unavailable function. + int &ir = foo(1); + double &dr = foo(1.0); + foo(sp); + foo(); +} diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp index 98df1dbfe81e1..3f1d6a8a55c00 100644 --- a/test/SemaCXX/c99-variable-length-array.cpp +++ b/test/SemaCXX/c99-variable-length-array.cpp @@ -121,3 +121,12 @@ namespace PR8209 { (void)new vla_type; // expected-error{{variably}} } } + +namespace rdar8733881 { // rdar://8733881 + +static const int k_cVal3 = (int)(1000*0.2f); + int f() { + // Ok, fold to a constant size array as an extension. + char rgch[k_cVal3] = {0}; + } +} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index 61d1762be85f2..3441bae67076b 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -16,8 +16,9 @@ void test() { for (;s;) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}} - while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}} - while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}} + while (struct NewS *x=0) ; + while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}} + while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}} switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \ // expected-warning{{enumeration value 'E' not handled in switch}} diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index aa47ae0f48255..a7a178244c80d 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -378,3 +378,17 @@ namespace PR9336 { generic_list<generic_list<int> > l; array<array<int> > a = l; } + +namespace PR8800 { + struct A; + struct C { + operator A&(); + }; + void f() { + C c; + A& a1(c); + A& a2 = c; + A& a3 = static_cast<A&>(c); + A& a4 = (A&)c; + } +} diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp index f3dadc445040f..7aca9d6a80abe 100644 --- a/test/SemaCXX/copy-assignment.cpp +++ b/test/SemaCXX/copy-assignment.cpp @@ -99,15 +99,17 @@ void test() { // <rdar://problem/8315440>: Don't crash // FIXME: the recovery here is really bad. -namespace test1 { // expected-note{{to match this '{'}} - template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} \ - // expected-note{{template parameter is declared here}} +namespace test1 { + template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} A(UndeclaredType n) : X(n) {} // expected-error{{expected ')'}} expected-note{{to match this '('}} \ - // expected-error{{use of undeclared identifier 'n'}} + // expected-error{{use of undeclared identifier 'n'}} \ + // expected-error{{expected ';' at end of declaration list}} \ + // expected-error{{field has incomplete type 'test1::A<char>'}} }; - template<typename T> class B : public A<T> { // expected-error{{declaration of 'T' shadows template parameter}} + template<typename T> class B : public A<T> { virtual void foo() {} }; - extern template class A<char>; // expected-error{{expected member name or ';' after declaration specifiers}} - extern template class B<char>; // expected-error{{expected member name or ';' after declaration specifiers}} -} // expected-error{{expected ';' after class}} // expected-error{{expected '}'}} + extern template class A<char>; // expected-note {{in instantiation of template class 'test1::A<char>' requested here}} \ + // expected-note {{definition of 'test1::A<char>' is not complete until the closing '}'}} + extern template class B<char>; +} diff --git a/test/SemaCXX/crashes.cpp b/test/SemaCXX/crashes.cpp index c75b0401fed69..b77248ef4104e 100644 --- a/test/SemaCXX/crashes.cpp +++ b/test/SemaCXX/crashes.cpp @@ -95,3 +95,12 @@ namespace PR9026 { Write(x); } } + +namespace PR10270 { + template<typename T> class C; + template<typename T> void f() { + if (C<T> == 1) // expected-error{{expected unqualified-id}} \ + // expected-error{{invalid '==' at end of declaration}} + return; + } +} diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp index d4ef7e33a1d1a..f61a92b71e1e5 100644 --- a/test/SemaCXX/decltype.cpp +++ b/test/SemaCXX/decltype.cpp @@ -16,3 +16,8 @@ void test_f2() { float &fr = f2(AC().a); } +namespace pr10154 { + class A{ + A(decltype(nullptr) param); + }; +}
\ No newline at end of file diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp index fc871cf379206..73e7578ecb6e6 100644 --- a/test/SemaCXX/enum-scoped.cpp +++ b/test/SemaCXX/enum-scoped.cpp @@ -119,3 +119,26 @@ namespace rdar9366066 { x % 8; // expected-error{{invalid operands to binary expression ('rdar9366066::X' and 'int')}} } } + +// Part 1 of PR10264 +namespace test5 { + namespace ns { + typedef unsigned Atype; + enum A : Atype; + } + enum ns::A : ns::Atype { + x, y, z + }; +} + +// Part 2 of PR10264 +namespace test6 { + enum A : unsigned; + struct A::a; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} + enum A::b; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} + int A::c; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} + void A::d(); // expected-error {{incomplete type 'test6::A' named in nested name specifier}} + void test() { + (void) A::e; // expected-error {{incomplete type 'test6::A' named in nested name specifier}} + } +} diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp index 95ece48e51feb..8a294face3806 100644 --- a/test/SemaCXX/expressions.cpp +++ b/test/SemaCXX/expressions.cpp @@ -63,3 +63,25 @@ int test2(int x) { return x && (-1); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} return x && (5); // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} } + +template<unsigned int A, unsigned int B> struct S +{ + enum { + e1 = A && B, + e2 = A && 7 // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + }; + + int foo() { + int x = A && B; + int y = B && 3; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} + + return x + y; + } +}; + +void test3() { + S<5, 8> s1; + S<2, 7> s2; + (void)s1.foo(); + (void)s2.foo(); +} diff --git a/test/SemaCXX/for-range-unused.cpp b/test/SemaCXX/for-range-unused.cpp new file mode 100644 index 0000000000000..7b7d84d3f9c87 --- /dev/null +++ b/test/SemaCXX/for-range-unused.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x -Wunused + +// PR9968: We used to warn that __range is unused in a dependent for-range. + +template <typename T> + struct Vector { + void doIt() { + int a; // expected-warning {{unused variable 'a'}} + + for (auto& e : elements) + ; + } + + T elements[10]; + }; + + +int main(int, char**) { + Vector<int> vector; + vector.doIt(); +} diff --git a/test/SemaCXX/function-overload-typo-crash.cpp b/test/SemaCXX/function-overload-typo-crash.cpp new file mode 100644 index 0000000000000..0fea312a97f2d --- /dev/null +++ b/test/SemaCXX/function-overload-typo-crash.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR10283 +void min(); +void min(int); + +template <typename T> void max(T); + +void f() { + fin(); //expected-error {{use of undeclared identifier 'fin'; did you mean 'min'}} + fax(0); //expected-error {{use of undeclared identifier 'fax'; did you mean 'max'}} +} diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp index ec37a0c9ac181..6e2bee7e301d1 100644 --- a/test/SemaCXX/generalized-initializers.cpp +++ b/test/SemaCXX/generalized-initializers.cpp @@ -85,23 +85,52 @@ namespace integral { namespace objects { + struct X1 { X1(int); }; + struct X2 { explicit X2(int); }; + template <int N> struct A { A() { static_assert(N == 0, ""); } A(int, double) { static_assert(N == 1, ""); } - A(int, int) { static_assert(N == 2, ""); } A(std::initializer_list<int>) { static_assert(N == 3, ""); } }; - void initialization() { + template <int N> + struct D { + D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}} + D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}} + }; + + template <int N> + struct E { + E(int, int) { static_assert(N == 0, ""); } + E(X1, int) { static_assert(N == 1, ""); } + }; + + void overload_resolution() { { A<0> a{}; } { A<0> a = {}; } - { A<1> a{1, 1.0}; } - { A<1> a = {1, 1.0}; } + // Narrowing conversions don't affect viability. The next two choose + // the initializer_list constructor. + { A<3> a{1, 1.0}; } // expected-error {{narrowing conversion}} + { A<3> a = {1, 1.0}; } // expected-error {{narrowing conversion}} { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; } { A<3> a = {1, 2, 3, 4, 5, 6, 7, 8}; } { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; } { A<3> a{1, 2}; } + + { D<0> d{1, 2, 3}; } + { D<1> d{1.0, 2.0, 3.0}; } + { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}} + + { E<0> e{1, 2}; } + } + + void explicit_implicit() { + { X1 x{0}; } + { X1 x = {0}; } + { X2 x{0}; } + { X2 x = {0}; } // expected-error {{explicit}} } struct C { @@ -172,3 +201,28 @@ namespace litb { B g({1, 2, 3}); } + +namespace aggregate { + // Direct list initialization does NOT allow braces to be elided! + struct S { + int ar[2]; + struct T { + int i1; + int i2; + } t; + struct U { + int i1; + } u[2]; + struct V { + int var[2]; + } v; + }; + + void test() { + S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error + S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced + S s3{ 1, 2, 3, 4, 5, 6 }; // xpected-error + S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // xpected-error + S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // xpected-error + } +} diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index 2d08ea9a428f3..186e32126a39a 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -42,3 +42,16 @@ namespace pr6206 { void pr6373(const unsigned x = 0) { unsigned max = 80 / x; } + + +// rdar://9204520 +namespace rdar9204520 { + +struct A { + static const int B = int(0.75 * 1000 * 1000); +}; + +int foo() { return A::B; } +} + + diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp index 1b8c523e4586f..7ca1f0e4513e4 100644 --- a/test/SemaCXX/member-init.cpp +++ b/test/SemaCXX/member-init.cpp @@ -48,3 +48,7 @@ struct CheckExcSpecFail { CheckExcSpecFail() noexcept(true) = default; // expected-error {{exception specification of explicitly defaulted default constructor does not match the calculated one}} ThrowCtor tc = 123; }; + +struct TypedefInit { + typedef int A = 0; // expected-error {{illegal initializer}} +}; diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index de3b211acf500..cf6481015a823 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -296,3 +296,19 @@ namespace PR9973 { mem_fn(&test::nullary_v)(t); // expected-note{{in instantiation of}} } } + +namespace test8 { + struct A { int foo; }; + int test1() { + // Verify that we perform (and check) an lvalue conversion on the operands here. + return (*((A**) 0)) // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}} + ->**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}} + } + + int test2() { + // Verify that we perform (and check) an lvalue conversion on the operands here. + // TODO: the .* should itself warn about being a dereference of null. + return (*((A*) 0)) + .**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}} + } +} diff --git a/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp new file mode 100644 index 0000000000000..fd0c976bdd78d --- /dev/null +++ b/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s + +namespace fizbin { class Foobar; } // expected-note{{'fizbin::Foobar' declared here}} +Foobar *my_bar = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} \ + // expected-error{{expected a type}} + +namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}} +int Double(int x) { return x + x; } +void empty() { + Double(toFoobar()); // expected-error{{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}} +} + +namespace fizbin { + namespace baztool { bool toFoobar() { return true; } } // expected-note{{'fizbin::baztool' declared here}} + namespace nested { bool moreFoobar() { return true; } } // expected-note{{'fizbin::nested::moreFoobar' declared here}} + namespace nested { bool lessFoobar() { return true; } } // expected-note{{'fizbin::nested' declared here}} \ + // 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}} + }; +} +void Check() { // expected-note{{'Check' declared here}} + if (toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}} + if (noFoobar()) Double(7); // expected-error{{use of undeclared identifier 'noFoobar'; did you mean 'barstool::toFoobar'?}} + if (moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'moreFoobar'; did you mean 'fizbin::nested::moreFoobar'}} + 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 (moFoobin()) Double(7); // expected-error{{use of undeclared identifier 'moFoobin'}} +} + +void Alt() { + Cleck(); // expected-error{{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}} +} + +namespace N { + namespace inner { + class myvector { /* ... */ }; // expected-note{{'inner::myvector' declared here}} + } + + void f() { + myvector v; // expected-error{{unknown type name 'myvector'; did you mean 'inner::myvector'?}} + } +} + +namespace realstd { + inline namespace __1 { + class mylinkedlist { /* ... */ }; // expected-note 2 {{'realstd::mylinkedlist' declared here}} + } + + class linkedlist { /* ... */ }; +} + +void f() { + mylinkedlist v; // expected-error{{unknown type name 'mylinkedlist'; did you mean 'realstd::mylinkedlist'?}} + nylinkedlist w; // expected-error{{unknown type name 'nylinkedlist'; did you mean 'realstd::mylinkedlist'?}} +} + +// Test case from http://llvm.org/bugs/show_bug.cgi?id=10318 +namespace llvm { + template <typename T> class GraphWriter {}; // expected-note{{'llvm::GraphWriter' declared here}} +} + +struct S {}; +void bar() { + GraphWriter<S> x; //expected-error{{no template named 'GraphWriter'; did you mean 'llvm::GraphWriter'?}} + +} diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index fef70931717e8..ee6ca88573749 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -261,8 +261,27 @@ namespace PR8159 { namespace rdar7980179 { class A { void f0(); }; // expected-note {{previous}} - int A::f0() {} // expected-error {{out-of-line definition of 'rdar7980179::A::f0' differ from the declaration in the return type}} + int A::f0() {} // expected-error {{out-of-line definition of 'rdar7980179::A::f0' differs from the declaration in the return type}} } namespace alias = A; double *dp = (alias::C*)0; // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'alias::C *'}} + +// http://llvm.org/PR10109 +namespace PR10109 { +template<typename T> +struct A { +protected: + struct B; + struct B::C; // expected-error {{requires a template parameter list}} \ + // expected-error {{no struct named 'C'}} +}; + +template<typename T> +struct A2 { +protected: + struct B; +}; +template <typename T> +struct A2<T>::B::C; // expected-error {{no struct named 'C'}} +} diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index 13ef461e7c0d8..efdfa0f066dbf 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -389,3 +389,11 @@ namespace PR7702 { new DoesNotExist; // expected-error {{expected a type}} } } + +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}} + } +} diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp new file mode 100644 index 0000000000000..fab6f10ab7852 --- /dev/null +++ b/test/SemaCXX/null_in_arithmetic_ops.cpp @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -fblocks -Wnull-arithmetic -verify %s +#include <stddef.h> + +void f() { + int a; + bool b; + void (^c)(); + class X; + void (X::*d) (); + extern void e(); + int f[2]; + const void *v; + + a = 0 ? NULL + a : a + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL - a : a - NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL / a : a / NULL; // expected-warning 2{{use of NULL in arithmetic operation}} \ + // expected-warning {{division by zero is undefined}} + a = 0 ? NULL * a : a * NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL >> a : a >> NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL << a : a << NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL % a : a % NULL; // expected-warning 2{{use of NULL in arithmetic operation}} \ + expected-warning {{remainder by zero is undefined}} + a = 0 ? NULL & a : a & NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL | a : a | NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + a = 0 ? NULL ^ a : a ^ NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + + // Check for warnings or errors when doing arithmetic on pointers and other + // types. + v = 0 ? NULL + &a : &a + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + v = 0 ? NULL + c : c + NULL; // \ + expected-error {{invalid operands to binary expression ('long' and 'void (^)()')}} \ + expected-error {{invalid operands to binary expression ('void (^)()' and 'long')}} + v = 0 ? NULL + d : d + NULL; // \ + expected-error {{invalid operands to binary expression ('long' and 'void (X::*)()')}} \ + expected-error {{invalid operands to binary expression ('void (X::*)()' and 'long')}} + v = 0 ? NULL + e : e + NULL; // expected-error 2{{arithmetic on a pointer to the function type 'void ()'}} + v = 0 ? NULL + f : f + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + v = 0 ? NULL + "f" : "f" + NULL; // expected-warning 2{{use of NULL in arithmetic operation}} + + // Using two NULLs should only give one error instead of two. + a = NULL + NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL - NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL / NULL; // expected-warning{{use of NULL in arithmetic operation}} \ + // expected-warning{{division by zero is undefined}} + a = NULL * NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL >> NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL << NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL % NULL; // expected-warning{{use of NULL in arithmetic operation}} \ + // expected-warning{{remainder by zero is undefined}} + a = NULL & NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL | NULL; // expected-warning{{use of NULL in arithmetic operation}} + a = NULL ^ NULL; // expected-warning{{use of NULL in arithmetic operation}} + + a += NULL; // expected-warning{{use of NULL in arithmetic operation}} + a -= NULL; // expected-warning{{use of NULL in arithmetic operation}} + a /= NULL; // expected-warning{{use of NULL in arithmetic operation}} \ + // expected-warning{{division by zero is undefined}} + a *= NULL; // expected-warning{{use of NULL in arithmetic operation}} + a >>= NULL; // expected-warning{{use of NULL in arithmetic operation}} + a <<= NULL; // expected-warning{{use of NULL in arithmetic operation}} + a %= NULL; // expected-warning{{use of NULL in arithmetic operation}} \ + // expected-warning{{remainder by zero is undefined}} + a &= NULL; // expected-warning{{use of NULL in arithmetic operation}} + a |= NULL; // expected-warning{{use of NULL in arithmetic operation}} + a ^= NULL; // expected-warning{{use of NULL in arithmetic operation}} + + b = a < NULL || NULL < a; // expected-warning 2{{use of NULL in arithmetic operation}} + b = a > NULL || NULL > a; // expected-warning 2{{use of NULL in arithmetic operation}} + b = a <= NULL || NULL <= a; // expected-warning 2{{use of NULL in arithmetic operation}} + b = a >= NULL || NULL >= a; // expected-warning 2{{use of NULL in arithmetic operation}} + b = a == NULL || NULL == a; // expected-warning 2{{use of NULL in arithmetic operation}} + b = a != NULL || NULL != a; // expected-warning 2{{use of NULL in arithmetic operation}} + + b = &a < NULL || NULL < &a || &a > NULL || NULL > &a; + b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a; + b = &a == NULL || NULL == &a || &a != NULL || NULL != &a; + + b = 0 == a; + b = 0 == &a; + + b = NULL < NULL || NULL > NULL; + b = NULL <= NULL || NULL >= NULL; + b = NULL == NULL || NULL != NULL; + + b = ((NULL)) != a; // expected-warning{{use of NULL in arithmetic operation}} + + // Check that even non-standard pointers don't warn. + b = c == NULL || NULL == c || c != NULL || NULL != c; + b = d == NULL || NULL == d || d != NULL || NULL != d; + b = e == NULL || NULL == e || e != NULL || NULL != e; + b = f == NULL || NULL == f || f != NULL || NULL != f; + b = "f" == NULL || NULL == "f" || "f" != NULL || NULL != "f"; +} diff --git a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp new file mode 100644 index 0000000000000..e839ed116f8de --- /dev/null +++ b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fsyntax-only -fblocks -std=c++0x -verify %s + +void foo() { + int a; + bool b; + + a = 0 ? nullptr + a : a + nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr - a : a - nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr / a : a / nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr * a : a * nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr >> a : a >> nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr << a : a << nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr % a : a % nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr & a : a & nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr | a : a | nullptr; // expected-error 2{{invalid operands to binary expression}} + a = 0 ? nullptr ^ a : a ^ nullptr; // expected-error 2{{invalid operands to binary expression}} + + // Using two nullptrs should only give one error instead of two. + a = nullptr + nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr - nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr / nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr * nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr >> nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr << nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr % nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr & nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr | nullptr; // expected-error{{invalid operands to binary expression}} + a = nullptr ^ nullptr; // expected-error{{invalid operands to binary expression}} + + a += nullptr; // expected-error{{invalid operands to binary expression}} + a -= nullptr; // expected-error{{invalid operands to binary expression}} + a /= nullptr; // expected-error{{invalid operands to binary expression}} + a *= nullptr; // expected-error{{invalid operands to binary expression}} + a >>= nullptr; // expected-error{{invalid operands to binary expression}} + a <<= nullptr; // expected-error{{invalid operands to binary expression}} + a %= nullptr; // expected-error{{invalid operands to binary expression}} + a &= nullptr; // expected-error{{invalid operands to binary expression}} + a |= nullptr; // expected-error{{invalid operands to binary expression}} + a ^= nullptr; // expected-error{{invalid operands to binary expression}} + + b = a < nullptr || nullptr < a; // expected-error 2{{invalid operands to binary expression}} + b = a > nullptr || nullptr > a; // expected-error 2{{invalid operands to binary expression}} + b = a <= nullptr || nullptr <= a; // expected-error 2{{invalid operands to binary expression}} + b = a >= nullptr || nullptr >= a; // expected-error 2{{invalid operands to binary expression}} + b = a == nullptr || nullptr == a; // expected-error 2{{invalid operands to binary expression}} + b = a != nullptr || nullptr != a; // expected-error 2{{invalid operands to binary expression}} + + b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a; + b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a; + b = &a == nullptr || nullptr == &a || &a != nullptr || nullptr != &a; + + b = nullptr < nullptr || nullptr > nullptr; + b = nullptr <= nullptr || nullptr >= nullptr; + b = nullptr == nullptr || nullptr != nullptr; + + b = ((nullptr)) != a; // expected-error{{invalid operands to binary expression}} + + void (^c)(); + c = nullptr; + b = c == nullptr || nullptr == c || c != nullptr || nullptr != c; + + class X; + void (X::*d) (); + d = nullptr; + b = d == nullptr || nullptr == d || d != nullptr || nullptr != d; + + extern void e(); + b = e == nullptr || nullptr == e || e != nullptr || nullptr != e; + + int f[2]; + b = f == nullptr || nullptr == f || f != nullptr || nullptr != f; + b = "f" == nullptr || nullptr == "f" || "f" != nullptr || nullptr != "f"; +} diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp index 5a87cc8e67e6c..73f12a902723a 100644 --- a/test/SemaCXX/overloaded-name.cpp +++ b/test/SemaCXX/overloaded-name.cpp @@ -12,3 +12,19 @@ void test(bool b) { (void)(b? ovl<float> : &ovl); // expected-error{{cannot resolve overloaded function 'ovl' from context}} (void)(b? ovl<float> : ovl<float>); } + +namespace rdar9623945 { + void f(...) { + } + + class X { + public: + const char* text(void); + void g(void) { + f(text()); + f(text); // expected-error{{a bound member function may only be called}} + f(text()); + f(text); // expected-error{{a bound member function may only be called}} + } + }; +} diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index b457f6ace55aa..2f98a277f6385 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -69,3 +69,14 @@ namespace PR10057 { return S() = value; } } + +namespace return_has_expr { + struct S { + S() { + return 42; // expected-error {{constructor 'S' should not return a value}} + } + ~S() { + return 42; // expected-error {{destructor '~S' should not return a value}} + } + }; +} diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index df0080fac94a0..3ca07b0215c39 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -101,3 +101,21 @@ void t6(Foo somearg, ... ) { __builtin_va_start(list, somearg); } +void t7(int n, ...) { + __builtin_va_list list; + __builtin_va_start(list, n); + (void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}} + __builtin_va_end(list); +} + +struct Abstract { + virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}} +}; + +void t8(int n, ...) { + __builtin_va_list list; + __builtin_va_start(list, n); + (void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}} + __builtin_va_end(list); +} + diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 9ae2c82fc530f..4d3d93974c169 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -176,10 +176,10 @@ void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16, (void)(to_c16 * to_c16e); (void)(to_c16 / to_c16e); (void)(rto_c16 = c16e); // expected-error{{no viable overloaded '='}} - (void)(rto_c16 += to_c16e); // expected-error{{expression is not assignable}} - (void)(rto_c16 -= to_c16e); // expected-error{{expression is not assignable}} - (void)(rto_c16 *= to_c16e); // expected-error{{expression is not assignable}} - (void)(rto_c16 /= to_c16e); // expected-error{{expression is not assignable}} + (void)(rto_c16 += to_c16e); + (void)(rto_c16 -= to_c16e); + (void)(rto_c16 *= to_c16e); + (void)(rto_c16 /= to_c16e); (void)(Cond? to_c16 : to_c16e); (void)(Cond? to_ll16e : to_ll16); diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp index 792467e5f86bf..d8c26efcfb429 100644 --- a/test/SemaCXX/virtuals.cpp +++ b/test/SemaCXX/virtuals.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++0x %s class A { virtual void f(); - virtual void g() = 0; + virtual void g() = 0; // expected-note{{unimplemented pure virtual method 'g' in 'A'}} void h() = 0; // expected-error {{'h' is not virtual and cannot be declared pure}} void i() = 1; // expected-error {{initializer on function does not look like a pure-specifier}} @@ -19,20 +19,29 @@ virtual void A::k() { } // expected-error{{'virtual' can only be specified insid class B : public A { // Needs to recognize that overridden function is virtual. - //void g() = 0; + void g() = 0; // Needs to recognize that function does not override. - //void g(int) = 0; + void g(int) = 0; // expected-error{{'g' is not virtual and cannot be declared pure}} }; // Needs to recognize invalid uses of abstract classes. -/* -A fn(A) +A fn(A) // expected-error{{parameter type 'A' is an abstract class}} \ + // expected-error{{return type 'A' is an abstract class}} { - A a; - static_cast<A>(0); + A a; // expected-error{{variable type 'A' is an abstract class}} + (void)static_cast<A>(0); try { - } catch(A) { + } catch(A) { // expected-error{{variable type 'A' is an abstract class}} } } -*/ + +namespace rdar9670557 { + typedef int func(int); + func *a(); + struct X { + virtual func f = 0; + virtual func (g) = 0; + func *h = 0; + }; +} diff --git a/test/SemaCXX/warn-bad-memaccess.cpp b/test/SemaCXX/warn-bad-memaccess.cpp index e7d095f0edcef..9a998f020cb4a 100644 --- a/test/SemaCXX/warn-bad-memaccess.cpp +++ b/test/SemaCXX/warn-bad-memaccess.cpp @@ -38,6 +38,46 @@ void test_warn() { memcpy(0, &x1, sizeof x1); // \ // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class}} \ // expected-note {{explicitly cast the pointer to silence this warning}} + + __builtin_memset(&x1, 0, sizeof x1); // \ + // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin_memset(&x2, 0, sizeof x2); // \ + // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + + __builtin_memmove(&x1, 0, sizeof x1); // \ + // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin_memmove(0, &x1, sizeof x1); // \ + // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin_memcpy(&x1, 0, sizeof x1); // \ + // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin_memcpy(0, &x1, sizeof x1); // \ + // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + + __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); // \ + // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); // \ + // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + + __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); // \ + // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); // \ + // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); // \ + // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} + __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); // \ + // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ + // expected-note {{explicitly cast the pointer to silence this warning}} } void test_nowarn(void *void_ptr) { @@ -68,3 +108,5 @@ namespace N { N::memset(&x1, 0, sizeof x1); } } + + diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp new file mode 100644 index 0000000000000..90ac50472e98d --- /dev/null +++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-sizeof-array-argument %s +// +extern "C" void *memset(void *, int, unsigned); +extern "C" void *memmove(void *s1, const void *s2, unsigned n); +extern "C" void *memcpy(void *s1, const void *s2, unsigned n); + +struct S {int a, b, c, d;}; +typedef S* PS; + +struct Foo {}; +typedef const Foo& CFooRef; +typedef const Foo CFoo; +typedef volatile Foo VFoo; +typedef const volatile Foo CVFoo; + +typedef double Mat[4][4]; + +template <class Dest, class Source> +inline Dest bit_cast(const Source& source) { + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; +} + +// http://www.lysator.liu.se/c/c-faq/c-2.html#2-6 +void f(Mat m, const Foo& const_foo, char *buffer) { + S s; + S* ps = &s; + PS ps2 = &s; + char arr[5]; + char* parr[5]; + Foo foo; + char* heap_buffer = new char[42]; + + /* Should warn */ + memset(&s, 0, sizeof(&s)); // \ + // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + memset(ps, 0, sizeof(ps)); // \ + // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + memset(ps2, 0, sizeof(ps2)); // \ + // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + memset(ps2, 0, sizeof(typeof(ps2))); // \ + // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} + memset(ps2, 0, sizeof(PS)); // \ + // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} + memset(heap_buffer, 0, sizeof(heap_buffer)); // \ + // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}} + + memcpy(&s, 0, sizeof(&s)); // \ + // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the destination}} + memcpy(0, &s, sizeof(&s)); // \ + // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the source}} + + /* Shouldn't warn */ + memset((void*)&s, 0, sizeof(&s)); + memset(&s, 0, sizeof(s)); + memset(&s, 0, sizeof(S)); + memset(&s, 0, sizeof(const S)); + memset(&s, 0, sizeof(volatile S)); + memset(&s, 0, sizeof(volatile const S)); + memset(&foo, 0, sizeof(CFoo)); + memset(&foo, 0, sizeof(VFoo)); + memset(&foo, 0, sizeof(CVFoo)); + memset(ps, 0, sizeof(*ps)); + memset(ps2, 0, sizeof(*ps2)); + memset(ps2, 0, sizeof(typeof(*ps2))); + memset(arr, 0, sizeof(arr)); + memset(parr, 0, sizeof(parr)); + + memcpy(&foo, &const_foo, sizeof(Foo)); + memcpy((void*)&s, 0, sizeof(&s)); + memcpy(0, (void*)&s, sizeof(&s)); + char *cptr; + memcpy(&cptr, buffer, sizeof(cptr)); + memcpy((char*)&cptr, buffer, sizeof(cptr)); + + CFooRef cfoo = foo; + memcpy(&foo, &cfoo, sizeof(Foo)); + + memcpy(0, &arr, sizeof(arr)); + typedef char Buff[8]; + memcpy(0, &arr, sizeof(Buff)); + + unsigned char* puc; + bit_cast<char*>(puc); + + float* pf; + bit_cast<int*>(pf); + + int iarr[14]; + memset(&iarr[0], 0, sizeof iarr); + + int* iparr[14]; + memset(&iparr[0], 0, sizeof iparr); + + memset(m, 0, sizeof(Mat)); + + // Copy to raw buffer shouldn't warn either + memcpy(&foo, &arr, sizeof(Foo)); + memcpy(&arr, &foo, sizeof(Foo)); +} diff --git a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp index 698eccd1d2f09..ade6198fbd0d8 100644 --- a/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp +++ b/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp @@ -5,3 +5,10 @@ struct A { virtual void f() = 0; // expected-note 2 {{'f' declared here}} }; + +// Don't warn (or note) when calling the function on a pointer. (PR10195) +struct B { + A *a; + B() { a->f(); }; + ~B() { a->f(); }; +}; diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp index 81f22a796a0e6..5ba1f2a5f34b2 100644 --- a/test/SemaCXX/warn-unused-variables.cpp +++ b/test/SemaCXX/warn-unused-variables.cpp @@ -54,3 +54,29 @@ void unused_local_static() { static int y = 0; // expected-warning{{unused variable 'y'}} #pragma unused(x) } + +// PR10168 +namespace PR10168 { + // We expect a warning in the definition only for non-dependent variables, and + // a warning in the instantiation only for dependent variables. + template<typename T> + struct S { + void f() { + int a; // expected-warning {{unused variable 'a'}} + T b; // expected-warning 2{{unused variable 'b'}} + } + }; + + template<typename T> + void f() { + int a; // expected-warning {{unused variable 'a'}} + T b; // expected-warning 2{{unused variable 'b'}} + } + + void g() { + S<int>().f(); // expected-note {{here}} + S<char>().f(); // expected-note {{here}} + f<int>(); // expected-note {{here}} + f<char>(); // expected-note {{here}} + } +} |