Patch to support transparent_union arguments

passed to nonnull attributed functions. Implements radar
6857843.

llvm-svn: 114917
This commit is contained in:
Fariborz Jahanian 2010-09-27 22:42:37 +00:00
parent ec3bec0c7a
commit 3567c426c4
3 changed files with 39 additions and 0 deletions

View File

@ -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()))

View File

@ -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

View File

@ -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
}