Addressed review comments. Added test for the newly introduced diagnostic.

CodeGenCXX/no-opt-volatile-memcpy.cpp still fails. I tried checking for the 
absence of `@llvm.memcpy`, but the non-volatile array member of the `struct` is 
still `memcpy`-ed (good!). I have little to no experience with codegen tests, 
let alone llvm ir, I could use some help to adjust the offending test case.


http://reviews.llvm.org/D7060

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/DeclCXX.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CXX/class/class.union/p1.cpp
  test/CXX/drs/dr4xx.cpp
  test/SemaCXX/type-traits.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1339,6 +1339,8 @@
 def note_nontrivial_objc_ownership : Note<
   "because type %0 has a member with %select{no|no|__strong|__weak|"
   "__autoreleasing}1 ownership">;
+def note_nontrivial_has_volatile_member : Note<
+  "because field %0 has volatile qualified type">;
 
 def err_static_data_member_not_allowed_in_anon_struct : Error<
   "static data member %0 not allowed in anonymous struct">;
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -708,6 +708,16 @@
       data().IsStandardLayout = false;
     }
 
+    // C++11 [class.copy]p12, C++11 [class.copy]p25:
+    //   A [copy/move constructor, or copy/move assignment operator for a
+    //   class X] is trivial [...] if:
+    //    -- class X has no non-static data members of volatile-qualified
+    //       type, [...]
+    if (T.isVolatileQualified())
+      data().HasTrivialSpecialMembers &=
+          ~(SMF_CopyConstructor | SMF_MoveConstructor | SMF_CopyAssignment |
+            SMF_MoveAssignment);
+
     // Record if this field is the first non-literal or volatile field or base.
     if (!T->isLiteralType(Context) || T.isVolatileQualified())
       data().HasNonLiteralTypeFieldsOrBases = true;
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -6065,6 +6065,20 @@
       return false;
     }
 
+    // C++11 [class.copy]p12, C++11 [class.copy]p25:
+    //   A copy/move [constructor or assignment operator] for a class X is
+    //   trivial if
+    //    -- class X has no non-static data members of volatile-qualified
+    //       type, [...]
+    if ((CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXCopyAssignment ||
+         CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment) &&
+        FieldType.isVolatileQualified()) {
+      if (Diagnose)
+        S.Diag(FI->getLocation(), diag::note_nontrivial_has_volatile_member)
+            << FI;
+      return false;
+    }
+
     // Objective C ARC 4.3.5:
     //   [...] nontrivally ownership-qualified types are [...] not trivially
     //   default constructible, copy constructible, move constructible, copy
@@ -6192,6 +6206,10 @@
   //    -- for all of the non-static data members of its class that are of class
   //       type (or array thereof), each such class has a trivial [default
   //       constructor or destructor]
+  //   A copy/move [constructor or assignment operator] for a class X is
+  //   trivial if
+  //    -- class X has no non-static data members of volatile-qualified
+  //       type, [...]
   if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose))
     return false;
 
Index: test/CXX/class/class.union/p1.cpp
===================================================================
--- test/CXX/class/class.union/p1.cpp
+++ test/CXX/class/class.union/p1.cpp
@@ -31,6 +31,10 @@
   CopyAssign& operator=(CopyAssign& CA) { abort(); }
 };
 
+class Volatile {
+  volatile int a_; // expected-note {{because field 'a_' has volatile qualified type}}
+};
+
 class Dtor {
   ~Dtor() { abort(); } // expected-note 2 {{because type 'Dtor' has a user-provided destructor}} expected-note 2{{here}}
 };
@@ -44,6 +48,7 @@
   CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}}
   CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}}
   Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}}
+  Volatile volatile_; // expected-error {{union member 'volatile_' has a non-trivial copy constructor}}
   Okay okay;
 };
 
Index: test/CXX/drs/dr4xx.cpp
===================================================================
--- test/CXX/drs/dr4xx.cpp
+++ test/CXX/drs/dr4xx.cpp
@@ -1184,17 +1184,15 @@
   long n2 = s2;
 }
 
-namespace dr496 { // dr496: no
+namespace dr496 { // dr496: 3.7
   struct A { int n; };
   struct B { volatile int n; };
   int check1[ __is_trivially_copyable(const int) ? 1 : -1];
   int check2[!__is_trivially_copyable(volatile int) ? 1 : -1];
   int check3[ __is_trivially_constructible(A, const A&) ? 1 : -1];
-  // FIXME: This is wrong.
-  int check4[ __is_trivially_constructible(B, const B&) ? 1 : -1];
+  int check4[!__is_trivially_constructible(B, const B&) ? 1 : -1];
   int check5[ __is_trivially_assignable(A, const A&) ? 1 : -1];
-  // FIXME: This is wrong.
-  int check6[ __is_trivially_assignable(B, const B&) ? 1 : -1];
+  int check6[!__is_trivially_assignable(B, const B&) ? 1 : -1];
 }
 
 namespace dr497 { // dr497: yes
Index: test/SemaCXX/type-traits.cpp
===================================================================
--- test/SemaCXX/type-traits.cpp
+++ test/SemaCXX/type-traits.cpp
@@ -75,6 +75,9 @@
 struct NonTrivialDefault {
   NonTrivialDefault();
 };
+struct HasVolatileMember {
+  volatile int i;
+};
 
 struct HasDest { ~HasDest(); };
 class  HasPriv { int priv; };
@@ -1911,6 +1914,12 @@
   { int arr[F((__is_trivially_constructible(class_forward[])))]; }
   { int arr[F((__is_trivially_constructible(void)))]; }
 
+  { int arr[T((__is_trivially_constructible(HasVolatileMember)))]; }
+  { int arr[F((__is_trivially_constructible(HasVolatileMember, 
+                                            const HasVolatileMember &)))]; }
+  { int arr[F((__is_trivially_constructible(HasVolatileMember, 
+                                            HasVolatileMember &&)))]; }
+
   { int arr[T((__is_trivially_assignable(int&, int)))]; }
   { int arr[T((__is_trivially_assignable(int&, int&)))]; }
   { int arr[T((__is_trivially_assignable(int&, int&&)))]; }
@@ -1951,6 +1960,11 @@
                                          TrivialMoveButNotCopy)))]; }
   { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
                                          TrivialMoveButNotCopy&&)))]; }
+
+  { int arr[F((__is_trivially_assignable(HasVolatileMember, 
+                                         const HasVolatileMember &)))]; }
+  { int arr[F((__is_trivially_assignable(HasVolatileMember, 
+                                         HasVolatileMember &&)))]; }
 }
 
 void constructible_checks() {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to