diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-06-29 00:49:17 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-06-29 00:49:17 +0000 |
commit | 14b23277db34fd33292dd9ec23abb13e7cb72613 (patch) | |
tree | 4fc7a6ded88eef3d00ec1107d734e23263f646c4 | |
parent | 65cf624deb6ae4a235e567697cd1fc5ecb26cfcf (diff) |
Teach the __is_trivially_assignable and __is_trivially_constructible
type traits that assignment to/construction of a lifetime-qualified
object under ARC is *not* trivial. Fixes <rdar://problem/11738725>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159401 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 35 | ||||
-rw-r--r-- | test/SemaObjCXX/arc-type-traits.mm | 81 |
2 files changed, 113 insertions, 3 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 27ac381867..8efd465580 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3335,6 +3335,25 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT, return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen); } +/// \brief Determine whether T has a non-trivial Objective-C lifetime in +/// ARC mode. +static bool hasNontrivialObjCLifetime(QualType T) { + switch (T.getObjCLifetime()) { + case Qualifiers::OCL_ExplicitNone: + return false; + + case Qualifiers::OCL_Strong: + case Qualifiers::OCL_Weak: + case Qualifiers::OCL_Autoreleasing: + return true; + + case Qualifiers::OCL_None: + return T->isObjCLifetimeType(); + } + + llvm_unreachable("Unknown ObjC lifetime qualifier"); +} + static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc) { @@ -3408,8 +3427,14 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, ArgExprs.size())); if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; - - // The initialization succeeded; not make sure there are no non-trivial + + // Under Objective-C ARC, if the destination has non-trivial Objective-C + // lifetime, this is a non-trivial construction. + if (S.getLangOpts().ObjCAutoRefCount && + hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType())) + return false; + + // The initialization succeeded; now make sure there are no non-trivial // calls. return !Result.get()->hasNonTrivialCall(S.Context); } @@ -3590,6 +3615,12 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; + // Under Objective-C ARC, if the destination has non-trivial Objective-C + // lifetime, this is a non-trivial assignment. + if (Self.getLangOpts().ObjCAutoRefCount && + hasNontrivialObjCLifetime(LhsT.getNonReferenceType())) + return false; + return !Result.get()->hasNonTrivialCall(Self.Context); } } diff --git a/test/SemaObjCXX/arc-type-traits.mm b/test/SemaObjCXX/arc-type-traits.mm index 9877870f94..817724caf2 100644 --- a/test/SemaObjCXX/arc-type-traits.mm +++ b/test/SemaObjCXX/arc-type-traits.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -verify %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -verify -std=c++11 %s // Check the results of the various type-trait query functions on // lifetime-qualified types in ARC. @@ -9,6 +9,8 @@ #define TRAIT_IS_TRUE(Trait, Type) char JOIN2(Trait,__LINE__)[Trait(Type)? 1 : -1] #define TRAIT_IS_FALSE(Trait, Type) char JOIN2(Trait,__LINE__)[Trait(Type)? -1 : 1] +#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] // __has_nothrow_assign TRAIT_IS_TRUE(__has_nothrow_assign, __strong id); @@ -88,3 +90,80 @@ TRAIT_IS_TRUE(__is_standard_layout, __weak id); TRAIT_IS_TRUE(__is_standard_layout, __autoreleasing id); TRAIT_IS_TRUE(__is_standard_layout, __unsafe_unretained id); +// __is_trivally_assignable +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __strong id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __weak id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __autoreleasing id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __unsafe_unretained id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __strong id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __weak id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __autoreleasing id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __strong id&, __unsafe_unretained id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __strong id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __weak id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __autoreleasing id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __unsafe_unretained id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __strong id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __weak id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __autoreleasing id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __weak id&, __unsafe_unretained id&&); + +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __strong id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __weak id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __autoreleasing id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __unsafe_unretained id); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __strong id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __weak id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __autoreleasing id&&); +TRAIT_IS_FALSE_2(__is_trivially_assignable, __autoreleasing id&, __unsafe_unretained id&&); + +TRAIT_IS_TRUE_2(__is_trivially_assignable, __unsafe_unretained id&, __strong id); +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_TRUE_2(__is_trivially_assignable, __unsafe_unretained id&, __strong id&&); +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&&); + +// __is_trivally_constructible +TRAIT_IS_FALSE(__is_trivially_constructible, __strong id); +TRAIT_IS_FALSE(__is_trivially_constructible, __weak id); +TRAIT_IS_FALSE(__is_trivially_constructible, __autoreleasing id); +TRAIT_IS_TRUE(__is_trivially_constructible, __unsafe_unretained id); + +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __strong id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __weak id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __autoreleasing id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __unsafe_unretained id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __strong id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __weak id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __autoreleasing id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __strong id, __unsafe_unretained id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __strong id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __weak id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __autoreleasing id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __unsafe_unretained id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __strong id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __weak id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __autoreleasing id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __weak id, __unsafe_unretained id&&); + +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __strong id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __weak id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __autoreleasing id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __unsafe_unretained id); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __strong id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __weak id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __autoreleasing id&&); +TRAIT_IS_FALSE_2(__is_trivially_constructible, __autoreleasing id, __unsafe_unretained id&&); + +TRAIT_IS_TRUE_2(__is_trivially_constructible, __unsafe_unretained id, __strong id); +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_TRUE_2(__is_trivially_constructible, __unsafe_unretained id, __strong id&&); +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&&); + |