aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/Expr.cpp7
-rw-r--r--lib/Sema/SemaDeclAttr.cpp13
-rw-r--r--test/SemaObjC/nonnull.m19
3 files changed, 39 insertions, 0 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 9536b9bf24..708512ce46 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1862,6 +1862,13 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx,
if (getType()->isNullPtrType())
return true;
+ if (const RecordType *UT = getType()->getAsUnionType())
+ if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(this)){
+ const Expr *InitExpr = CLE->getInitializer();
+ if (const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr))
+ return ILE->getInit(0)->isNullPointerConstant(Ctx, NPC);
+ }
// This expression must be an integer type.
if (!getType()->isIntegerType() ||
(Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType()))
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 09feb50bd3..682a430ee4 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -371,6 +371,19 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
QualType T = getFunctionOrMethodArgType(d, I);
if (T->isAnyPointerType() || T->isBlockPointerType())
NonNullArgs.push_back(I);
+ else if (const RecordType *UT = T->getAsUnionType()) {
+ if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
+ RecordDecl *UD = UT->getDecl();
+ for (RecordDecl::field_iterator it = UD->field_begin(),
+ itend = UD->field_end(); it != itend; ++it) {
+ T = it->getType();
+ if (T->isAnyPointerType() || T->isBlockPointerType()) {
+ NonNullArgs.push_back(I);
+ break;
+ }
+ }
+ }
+ }
}
// No pointer arguments? The attribute in this case is
diff --git a/test/SemaObjC/nonnull.m b/test/SemaObjC/nonnull.m
index cbafc37e8e..6c45d97b06 100644
--- a/test/SemaObjC/nonnull.m
+++ b/test/SemaObjC/nonnull.m
@@ -48,3 +48,22 @@ foo (int i1, int i2, int i3, void (^cp1)(), void (^cp2)(), void (^cp3)())
}
void func5(int) NONNULL_ATTR; // no warning
+
+// rdar://6857843
+struct dispatch_object_s {
+ int x;
+};
+
+typedef union {
+ long first;
+ struct dispatch_object_s *_do;
+} dispatch_object_t __attribute__((transparent_union));
+
+__attribute__((nonnull))
+void _dispatch_queue_push_list(dispatch_object_t _head); // no warning
+
+void func6(dispatch_object_t _head) {
+ _dispatch_queue_push_list(0); // expected-warning {{null passed to a callee which requires a non-null argument}}
+ _dispatch_queue_push_list(_head._do); // no warning
+}
+