]> granicus.if.org Git - clang/commitdiff
[Sema][NFC] SequenceChecker: Add tests for references/members, and prepare for the...
authorBruno Ricci <riccibrun@gmail.com>
Fri, 15 Feb 2019 18:12:58 +0000 (18:12 +0000)
committerBruno Ricci <riccibrun@gmail.com>
Fri, 15 Feb 2019 18:12:58 +0000 (18:12 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354151 91177308-0d34-0410-b5e6-96231b3b80d8

test/SemaCXX/warn-unsequenced-cxx17.cpp [deleted file]
test/SemaCXX/warn-unsequenced.cpp

diff --git a/test/SemaCXX/warn-unsequenced-cxx17.cpp b/test/SemaCXX/warn-unsequenced-cxx17.cpp
deleted file mode 100644 (file)
index 3c221fb..0000000
+++ /dev/null
@@ -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
-}
index 6d4468cabfe5602af52aa80fe466ad5e2c815e89..7e970ff141472e61af002198481f95808bb5d0da 100644 (file)
@@ -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}}
 
 }