Author: brunoricci Date: Fri Feb 15 10:12:58 2019 New Revision: 354151 URL: http://llvm.org/viewvc/llvm-project?rev=354151&view=rev Log: [Sema][NFC] SequenceChecker: Add tests for references/members, and prepare for the C++17 tests
Add some tests for unsequenced operations with members and references. For now most of it is unhandled but it shows what work needs to be done. Also merge the tests for the C++17 sequencing rules in warn-unsequenced.cpp since we want to make sure that the appropriate warnings are still present in C++17 without duplicating the whole content of warn-unsequenced.cpp. Removed: cfe/trunk/test/SemaCXX/warn-unsequenced-cxx17.cpp Modified: cfe/trunk/test/SemaCXX/warn-unsequenced.cpp Removed: cfe/trunk/test/SemaCXX/warn-unsequenced-cxx17.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unsequenced-cxx17.cpp?rev=354150&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/warn-unsequenced-cxx17.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-unsequenced-cxx17.cpp (removed) @@ -1,8 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wno-unused %s - -void test() { - int xs[10]; - int *p = xs; - // expected-no-diagnostics - p[(long long unsigned)(p = 0)]; // ok -} Modified: cfe/trunk/test/SemaCXX/warn-unsequenced.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unsequenced.cpp?rev=354151&r1=354150&r2=354151&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-unsequenced.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-unsequenced.cpp Fri Feb 15 10:12:58 2019 @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-unused %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx11 -std=c++11 -Wno-unused -Wno-uninitialized -Wunsequenced %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx17 -std=c++17 -Wno-unused -Wno-uninitialized -Wunsequenced %s int f(int, int = 0); @@ -10,81 +11,107 @@ struct S { int n; }; +// TODO: Implement the C++17 sequencing rules. void test() { int a; int xs[10]; ++a = 0; // ok - a + ++a; // expected-warning {{unsequenced modification and access to 'a'}} + a + ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} a = ++a; // ok - a + a++; // expected-warning {{unsequenced modification and access to 'a'}} - a = a++; // expected-warning {{multiple unsequenced modifications to 'a'}} + a + a++; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + a = a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} ++ ++a; // ok (a++, a++); // ok - ++a + ++a; // expected-warning {{multiple unsequenced modifications to 'a'}} - a++ + a++; // expected-warning {{multiple unsequenced modifications}} + ++a + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + a++ + a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} (a++, a) = 0; // ok, increment is sequenced before value computation of LHS a = xs[++a]; // ok - a = xs[a++]; // expected-warning {{multiple unsequenced modifications}} - (a ? xs[0] : xs[1]) = ++a; // expected-warning {{unsequenced modification and access}} + a = xs[a++]; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + (a ? xs[0] : xs[1]) = ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}} a = (++a, ++a); // ok a = (a++, ++a); // ok - a = (a++, a++); // expected-warning {{multiple unsequenced modifications}} + a = (a++, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} f(a, a); // ok - 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}} + f(a = 0, a); // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + f(a, a += 0); // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + f(a = 0, a = 0); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} a = f(++a); // ok a = f(a++); // ok - a = f(++a, a++); // expected-warning {{multiple unsequenced modifications}} + a = f(++a, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} // Compound assignment "A OP= B" is equivalent to "A = A OP B" except that A // is evaluated only once. (++a, a) = 1; // ok (++a, a) += 1; // ok a = ++a; // ok - a += ++a; // expected-warning {{unsequenced modification and access}} + a += ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}} A agg1 = { a++, a++ }; // ok - A agg2 = { a++ + a, a++ }; // expected-warning {{unsequenced modification and access}} + A agg2 = { a++ + a, a++ }; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} - S str1(a++, a++); // expected-warning {{multiple unsequenced modifications}} + S str1(a++, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} S str2 = { a++, a++ }; // ok - S str3 = { a++ + a, a++ }; // expected-warning {{unsequenced modification and access}} + S str3 = { a++ + a, a++ }; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} 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}} + a = A { ++a, a++ }.x; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + A { ++a, a++ }.x + A { ++a, a++ }.y; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} (xs[2] && (a = 0)) + a; // ok (0 && (a = 0)) + a; // ok - (1 && (a = 0)) + a; // expected-warning {{unsequenced modification and access}} + (1 && (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (xs[3] || (a = 0)) + a; // ok - (0 || (a = 0)) + a; // expected-warning {{unsequenced modification and access}} + (0 || (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (1 || (a = 0)) + a; // ok (xs[4] ? a : ++a) + a; // ok - (0 ? a : ++a) + a; // expected-warning {{unsequenced modification and access}} + (0 ? a : ++a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (1 ? a : ++a) + a; // ok - (0 ? a : a++) + a; // expected-warning {{unsequenced modification and access}} + (0 ? a : a++) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} (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}} + (++a, xs[6] ? ++a : 0) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} // Here, the read of the fourth 'a' might happen before or after the write to // the second 'a'. - a += (a++, a) + a; // expected-warning {{unsequenced modification and access}} + a += (a++, a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} int *p = xs; a = *(a++, p); // ok a = a++ && a; // ok - p[(long long unsigned)(p = 0)]; // expected-warning {{unsequenced modification and access to 'p'}} + p[(long long unsigned)(p = 0)]; // cxx11-warning {{unsequenced modification and access to 'p'}} A *q = &agg1; - (q = &agg2)->y = q->x; // expected-warning {{unsequenced modification and access to 'q'}} + (q = &agg2)->y = q->x; // cxx11-warning {{unsequenced modification and access to 'q'}} + // TODO cxx17-warning@-1 {{unsequenced modification and access to 'q'}} // This has undefined behavior if a == 0; otherwise, the side-effect of the // increment is sequenced before the value computation of 'f(a, a)', which is @@ -102,19 +129,196 @@ void test() { (a -= 128) &= 128; // ok ++a += 1; // ok - xs[8] ? ++a + a++ : 0; // expected-warning {{multiple unsequenced modifications}} - xs[8] ? 0 : ++a + a++; // expected-warning {{multiple unsequenced modifications}} + xs[8] ? ++a + a++ : 0; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + xs[8] ? 0 : ++a + a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} xs[8] ? ++a : a++; // ok - xs[8] && (++a + a++); // expected-warning {{multiple unsequenced modifications}} - xs[8] || (++a + a++); // expected-warning {{multiple unsequenced modifications}} + xs[8] && (++a + a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + xs[8] || (++a + a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} (__builtin_classify_type(++a) ? 1 : 0) + ++a; // ok (__builtin_constant_p(++a) ? 1 : 0) + ++a; // ok (__builtin_object_size(&(++a, a), 0) ? 1 : 0) + ++a; // ok - (__builtin_expect(++a, 0) ? 1 : 0) + ++a; // expected-warning {{multiple unsequenced modifications}} + (__builtin_expect(++a, 0) ? 1 : 0) + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} } +namespace members { + +struct S1 { + unsigned bf1 : 2; + unsigned bf2 : 2; + unsigned a; + unsigned b; + + void member_f(S1 &s); +}; + +void S1::member_f(S1 &s) { + int xs[10]; + + ++a + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}} + a + ++a; // cxx11-warning {{unsequenced modification and access to 'a'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'a'}} + ++a + ++b; // no-warning + a + ++b; // no-warning + + // TODO: Warn here. + ++s.a + ++s.a; // no-warning TODO {{multiple unsequenced modifications to}} + s.a + ++s.a; // no-warning TODO {{unsequenced modification and access to}} + ++s.a + ++s.b; // no-warning + s.a + ++s.b; // no-warning + + ++a + ++s.a; // no-warning + a + ++s.a; // no-warning + ++a + ++s.b; // no-warning + a + ++s.b; // no-warning + + // TODO Warn here for bit-fields in the same memory location. + ++bf1 + ++bf1; // cxx11-warning {{multiple unsequenced modifications to 'bf1'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'bf1'}} + bf1 + ++bf1; // cxx11-warning {{unsequenced modification and access to 'bf1'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'bf1'}} + ++bf1 + ++bf2; // no-warning TODO {{multiple unsequenced modifications to}} + bf1 + ++bf2; // no-warning TODO {{unsequenced modification and access to}} + + // TODO Warn here for bit-fields in the same memory location. + ++s.bf1 + ++s.bf1; // no-warning TODO {{multiple unsequenced modifications to}} + s.bf1 + ++s.bf1; // no-warning TODO {{unsequenced modification and access to}} + ++s.bf1 + ++s.bf2; // no-warning TODO {{multiple unsequenced modifications to}} + s.bf1 + ++s.bf2; // no-warning TODO {{unsequenced modification and access to}} + + ++bf1 + ++s.bf1; // no-warning + bf1 + ++s.bf1; // no-warning + ++bf1 + ++s.bf2; // no-warning + bf1 + ++s.bf2; // no-warning +} + +struct S2 { + union { unsigned x, y; }; + void f2(); +}; + +void S2::f2() { + ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}} + x + ++x; // no-warning TODO {{unsequenced modification and access to}} + ++x + ++y; // no-warning + x + ++y; // no-warning +} + +void f2(S2 &s) { + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning +} + +struct S3 { + union { + union { + unsigned x; + }; + }; + unsigned y; + void f3(); +}; + +void S3::f3() { + ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}} + x + ++x; // no-warning TODO {{unsequenced modification and access to}} + ++x + ++y; // no-warning + x + ++y; // no-warning +} + +void f3(S3 &s) { + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning +} + +struct S4 : S3 { + unsigned y; + void f4(); +}; + +void S4::f4() { + ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}} + x + ++x; // no-warning TODO {{unsequenced modification and access to}} + ++x + ++y; // no-warning + x + ++y; // no-warning + ++S3::y + ++y; // no-warning + S3::y + ++y; // no-warning +} + +void f4(S4 &s) { + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning + ++s.S3::y + ++s.y; // no-warning + s.S3::y + ++s.y; // no-warning +} + +static union { + unsigned Ux; + unsigned Uy; +}; + +void f5() { + ++Ux + ++Ux; // no-warning TODO {{multiple unsequenced modifications to}} + Ux + ++Ux; // no-warning TODO {{unsequenced modification and access to}} + ++Ux + ++Uy; // no-warning + Ux + ++Uy; // no-warning +} + +void f6() { + struct S { unsigned x, y; } s; + ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}} + s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}} + ++s.x + ++s.y; // no-warning + s.x + ++s.y; // no-warning + + struct { unsigned x, y; } t; + ++t.x + ++t.x; // no-warning TODO {{multiple unsequenced modifications to}} + t.x + ++t.x; // no-warning TODO {{unsequenced modification and access to}} + ++t.x + ++t.y; // no-warning + t.x + ++t.y; // no-warning +} + +} // namespace members + +namespace references { +void reference_f() { + // TODO: Check that we can see through references. + // For now this is completely unhandled. + int a; + int xs[10]; + int &b = a; + int &c = b; + int &ra1 = c; + int &ra2 = b; + int other; + + ++ra1 + ++ra2; // no-warning TODO {{multiple unsequenced modifications to}} + ra1 + ++ra2; // no-warning TODO {{unsequenced modification and access to}} + ++ra1 + ++other; // no-warning + ra1 + ++other; // no-warning + + // Make sure we handle reference cycles. + int &ref_cycle = ref_cycle; + ++ref_cycle + ++ref_cycle; // cxx11-warning {{multiple unsequenced modifications to 'ref_cycle'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'ref_cycle'}} + ref_cycle + ++ref_cycle; // cxx11-warning {{unsequenced modification and access to 'ref_cycle'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'ref_cycle'}} +} +} // namespace references + namespace templates { template <typename T> @@ -146,26 +350,31 @@ int Foo<X>::Run() { if (static_cast<E>((num = bar.get()) < 5) || static_cast<E>(num < 10)) { } if (static_cast<E>((num = bar.get()) < 5) && static_cast<E>(num < 10)) { } - // expected-warning@-1 {{unsequenced modification and access to 'num'}} + // cxx11-warning@-1 {{unsequenced modification and access to 'num'}} + // cxx17-warning@-2 {{unsequenced modification and access to 'num'}} foo(num++, num++); - // expected-warning@-1 2{{multiple unsequenced modifications to 'num'}} + // cxx11-warning@-1 2{{multiple unsequenced modifications to 'num'}} + // cxx17-warning@-2 2{{multiple unsequenced modifications to 'num'}} return 1; } int x = Foo<int>().Run(); -// expected-note@-1 {{in instantiation of member function 'templates::Foo<int>::Run'}} +// cxx11-note@-1 {{in instantiation of member function 'templates::Foo<int>::Run'}} +// cxx17-note@-2 {{in instantiation of member function 'templates::Foo<int>::Run'}} template <typename T> int Run2() { T t = static_cast<T>(0); return (t = static_cast<T>(1)) && t; - // expected-warning@-1 {{unsequenced modification and access to 't'}} + // cxx11-warning@-1 {{unsequenced modification and access to 't'}} + // cxx17-warning@-2 {{unsequenced modification and access to 't'}} } int y = Run2<bool>(); int z = Run2<E>(); -// expected-note@-1{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}} +// cxx11-note@-1{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}} +// cxx17-note@-2{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits