aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-06-29 00:49:17 +0000
committerDouglas Gregor <dgregor@apple.com>2012-06-29 00:49:17 +0000
commit14b23277db34fd33292dd9ec23abb13e7cb72613 (patch)
tree4fc7a6ded88eef3d00ec1107d734e23263f646c4
parent65cf624deb6ae4a235e567697cd1fc5ecb26cfcf (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.cpp35
-rw-r--r--test/SemaObjCXX/arc-type-traits.mm81
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&&);
+