From 6fa6942dda7fa608d8eeabd3e81b7423f5678090 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 23 Jul 2012 04:23:39 +0000 Subject: [PATCH] When we have an Objective-C object with non-trivial lifetime in a structor class under ARC, that struct/class does not have a trivial move constructor or move assignment operator. Fixes the rest of . llvm-svn: 160615 --- clang/lib/AST/DeclCXX.cpp | 9 +++-- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp | 2 +- clang/test/SemaObjCXX/arc-type-traits.mm | 45 ++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 77e693c2c749..217b27a8d15f 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -765,7 +765,7 @@ NotASpecialMember:; // that does not explicitly have no lifetime makes the class a non-POD. // However, we delay setting PlainOldData to false in this case so that // Sema has a chance to diagnostic causes where the same class will be - // non-POD with Automatic Reference Counting but a POD without Instant Objects. + // non-POD with Automatic Reference Counting but a POD without ARC. // In this case, the class will become a non-POD class when we complete // the definition. ASTContext &Context = getASTContext(); @@ -1208,13 +1208,16 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { // Objective-C Automatic Reference Counting: // If a class has a non-static data member of Objective-C pointer // type (or array thereof), it is a non-POD type and its - // default constructor (if any), copy constructor, copy assignment - // operator, and destructor are non-trivial. + // default constructor (if any), copy constructor, move constructor, + // copy assignment operator, move assignment operator, and destructor are + // non-trivial. struct DefinitionData &Data = data(); Data.PlainOldData = false; Data.HasTrivialDefaultConstructor = false; Data.HasTrivialCopyConstructor = false; + Data.HasTrivialMoveConstructor = false; Data.HasTrivialCopyAssignment = false; + Data.HasTrivialMoveAssignment = false; Data.HasTrivialDestructor = false; Data.HasIrrelevantDestructor = false; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 430ce9f7f784..52aa5b72d197 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10026,7 +10026,7 @@ void Sema::ActOnFields(Scope* S, // However, here we check whether this particular class is only // non-POD because of the presence of an Objective-C pointer member. // If so, objects of this type cannot be shared between code compiled - // with instant objects and code compiled with manual retain/release. + // with ARC and code compiled with manual retain/release. if (getLangOpts().ObjCAutoRefCount && CXXRecord->hasObjectMember() && CXXRecord->getLinkage() == ExternalLinkage) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2a5c0dae4362..8f03f81e5655 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2774,7 +2774,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, FieldBaseElementType->isObjCRetainableType() && FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None && FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { - // Instant objects: + // ARC: // Default-initialize Objective-C pointers to NULL. CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, diff --git a/clang/test/SemaObjCXX/arc-type-traits.mm b/clang/test/SemaObjCXX/arc-type-traits.mm index 817724caf2de..67bab00cf978 100644 --- a/clang/test/SemaObjCXX/arc-type-traits.mm +++ b/clang/test/SemaObjCXX/arc-type-traits.mm @@ -12,47 +12,72 @@ #define TRAIT_IS_TRUE_2(Trait, Type1, Type2) char JOIN2(Trait,__LINE__)[Trait(Type1, Type2)? 1 : -1] #define TRAIT_IS_FALSE_2(Trait, Type1, Type2) char JOIN2(Trait,__LINE__)[Trait(Type1, Type2)? -1 : 1] +struct HasStrong { id obj; }; +struct HasWeak { __weak id obj; }; +struct HasUnsafeUnretained { __unsafe_unretained id obj; }; + // __has_nothrow_assign TRAIT_IS_TRUE(__has_nothrow_assign, __strong id); TRAIT_IS_TRUE(__has_nothrow_assign, __weak id); TRAIT_IS_TRUE(__has_nothrow_assign, __autoreleasing id); TRAIT_IS_TRUE(__has_nothrow_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_assign, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_assign, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_assign, HasUnsafeUnretained); // __has_nothrow_copy TRAIT_IS_TRUE(__has_nothrow_copy, __strong id); TRAIT_IS_TRUE(__has_nothrow_copy, __weak id); TRAIT_IS_TRUE(__has_nothrow_copy, __autoreleasing id); TRAIT_IS_TRUE(__has_nothrow_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_copy, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_copy, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_copy, HasUnsafeUnretained); // __has_nothrow_constructor TRAIT_IS_TRUE(__has_nothrow_constructor, __strong id); TRAIT_IS_TRUE(__has_nothrow_constructor, __weak id); TRAIT_IS_TRUE(__has_nothrow_constructor, __autoreleasing id); TRAIT_IS_TRUE(__has_nothrow_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasUnsafeUnretained); // __has_trivial_assign TRAIT_IS_FALSE(__has_trivial_assign, __strong id); TRAIT_IS_FALSE(__has_trivial_assign, __weak id); TRAIT_IS_FALSE(__has_trivial_assign, __autoreleasing id); TRAIT_IS_TRUE(__has_trivial_assign, __unsafe_unretained id); +TRAIT_IS_FALSE(__has_trivial_assign, HasStrong); +TRAIT_IS_FALSE(__has_trivial_assign, HasWeak); +TRAIT_IS_TRUE(__has_trivial_assign, HasUnsafeUnretained); // __has_trivial_copy TRAIT_IS_FALSE(__has_trivial_copy, __strong id); TRAIT_IS_FALSE(__has_trivial_copy, __weak id); TRAIT_IS_FALSE(__has_trivial_copy, __autoreleasing id); TRAIT_IS_TRUE(__has_trivial_copy, __unsafe_unretained id); +TRAIT_IS_FALSE(__has_trivial_copy, HasStrong); +TRAIT_IS_FALSE(__has_trivial_copy, HasWeak); +TRAIT_IS_TRUE(__has_trivial_copy, HasUnsafeUnretained); // __has_trivial_constructor TRAIT_IS_FALSE(__has_trivial_constructor, __strong id); TRAIT_IS_FALSE(__has_trivial_constructor, __weak id); TRAIT_IS_FALSE(__has_trivial_constructor, __autoreleasing id); TRAIT_IS_TRUE(__has_trivial_constructor, __unsafe_unretained id); +TRAIT_IS_FALSE(__has_trivial_constructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_constructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_constructor, HasUnsafeUnretained); // __has_trivial_destructor TRAIT_IS_FALSE(__has_trivial_destructor, __strong id); TRAIT_IS_FALSE(__has_trivial_destructor, __weak id); TRAIT_IS_TRUE(__has_trivial_destructor, __autoreleasing id); TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id); +TRAIT_IS_FALSE(__has_trivial_destructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_destructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_destructor, HasUnsafeUnretained); // __is_literal TRAIT_IS_TRUE(__is_literal, __strong id); @@ -71,12 +96,18 @@ TRAIT_IS_FALSE(__is_pod, __strong id); TRAIT_IS_FALSE(__is_pod, __weak id); TRAIT_IS_FALSE(__is_pod, __autoreleasing id); TRAIT_IS_TRUE(__is_pod, __unsafe_unretained id); +TRAIT_IS_FALSE(__is_pod, HasStrong); +TRAIT_IS_FALSE(__is_pod, HasWeak); +TRAIT_IS_TRUE(__is_pod, HasUnsafeUnretained); // __is_trivial TRAIT_IS_FALSE(__is_trivial, __strong id); TRAIT_IS_FALSE(__is_trivial, __weak id); TRAIT_IS_FALSE(__is_trivial, __autoreleasing id); TRAIT_IS_TRUE(__is_trivial, __unsafe_unretained id); +TRAIT_IS_FALSE(__is_trivial, HasStrong); +TRAIT_IS_FALSE(__is_trivial, HasWeak); +TRAIT_IS_TRUE(__is_trivial, HasUnsafeUnretained); // __is_scalar TRAIT_IS_FALSE(__is_scalar, __strong id); @@ -126,6 +157,13 @@ TRAIT_IS_TRUE_2(__is_trivially_assignable, __unsafe_unretained id&, __weak id&&) TRAIT_IS_TRUE_2(__is_trivially_assignable, __unsafe_unretained id&, __autoreleasing id&&); TRAIT_IS_TRUE_2(__is_trivially_assignable, __unsafe_unretained id&, __unsafe_unretained id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, HasStrong&, HasStrong); +TRAIT_IS_FALSE_2(__is_trivially_assignable, HasStrong&, HasStrong&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, HasWeak&, HasWeak); +TRAIT_IS_FALSE_2(__is_trivially_assignable, HasWeak&, HasWeak&&); +TRAIT_IS_TRUE_2(__is_trivially_assignable, HasUnsafeUnretained&, HasUnsafeUnretained); +TRAIT_IS_TRUE_2(__is_trivially_assignable, HasUnsafeUnretained&, HasUnsafeUnretained&&); + // __is_trivally_constructible TRAIT_IS_FALSE(__is_trivially_constructible, __strong id); TRAIT_IS_FALSE(__is_trivially_constructible, __weak id); @@ -167,3 +205,10 @@ TRAIT_IS_TRUE_2(__is_trivially_constructible, __unsafe_unretained id, __weak id& TRAIT_IS_TRUE_2(__is_trivially_constructible, __unsafe_unretained id, __autoreleasing id&&); TRAIT_IS_TRUE_2(__is_trivially_constructible, __unsafe_unretained id, __unsafe_unretained id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, HasStrong, HasStrong); +TRAIT_IS_FALSE_2(__is_trivially_constructible, HasStrong, HasStrong&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, HasWeak, HasWeak); +TRAIT_IS_FALSE_2(__is_trivially_constructible, HasWeak, HasWeak&&); +TRAIT_IS_TRUE_2(__is_trivially_constructible, HasUnsafeUnretained, HasUnsafeUnretained); +TRAIT_IS_TRUE_2(__is_trivially_constructible, HasUnsafeUnretained, HasUnsafeUnretained&&); +