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()) + if (const CompoundLiteralExpr *CLE = dyn_cast(this)){ + const Expr *InitExpr = CLE->getInitializer(); + if (const InitListExpr *ILE = dyn_cast(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()) { + 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 +} +