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