Hi rsmith,
Implement CWG496, volatile qualified types are not trivially copyable, special
copy/move member functions are not trivial for classes with volatile qualified
non-static data members. Fixes PR21070. Breaks
CodeGenCXX/no-opt-volatile-memcpy.cpp, which specifically tests assignment for
a struct with a volatile member resulting in memcpy.
http://reviews.llvm.org/D7060
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/DeclCXX.cpp
lib/AST/Type.cpp
lib/Sema/SemaDeclCXX.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/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -1089,7 +1089,7 @@
bool QualType::isTriviallyCopyableType(ASTContext &Context) const {
if ((*this)->isArrayType())
- return Context.getBaseElementType(*this).isTrivialType(Context);
+ return Context.getBaseElementType(*this).isTriviallyCopyableType(Context);
if (Context.getLangOpts().ObjCAutoRefCount) {
switch (getObjCLifetime()) {
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/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: yes
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; };
@@ -1857,6 +1860,9 @@
{ int arr[T(__is_trivially_copyable(HasNonPOD))]; }
{ int arr[T(__is_trivially_copyable(DerivesHasCons))]; }
{ int arr[T(__is_trivially_copyable(DerivesHasRef))]; }
+ { int arr[T(__is_trivially_copyable(NonTrivialDefault))]; }
+ { int arr[T(__is_trivially_copyable(NonTrivialDefault[]))]; }
+ { int arr[T(__is_trivially_copyable(NonTrivialDefault[3]))]; }
{ int arr[F(__is_trivially_copyable(HasCopyAssign))]; }
{ int arr[F(__is_trivially_copyable(HasMoveAssign))]; }
@@ -1908,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&&)))]; }
@@ -1948,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