Handle nonnull attribute with optional argument number on

functions with arguments of transparent unions type.
// rdar://9584012

llvm-svn: 133941
This commit is contained in:
Fariborz Jahanian 2011-06-27 21:12:03 +00:00
parent a84be6c96b
commit f4aa279ce8
2 changed files with 39 additions and 13 deletions

View File

@ -361,6 +361,21 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
QT));
}
static void PossibleTransparentUnionPointerType(QualType &T) {
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) {
QualType QT = it->getType();
if (QT->isAnyPointerType() || QT->isBlockPointerType()) {
T = QT;
return;
}
}
}
}
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// GCC ignores the nonnull attribute on K&R style function prototypes, so we
// ignore it as well
@ -413,6 +428,8 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// Is the function argument a pointer type?
QualType T = getFunctionOrMethodArgType(d, x).getNonReferenceType();
PossibleTransparentUnionPointerType(T);
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
// FIXME: Should also highlight argument in decl.
S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
@ -428,21 +445,9 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (NonNullArgs.empty()) {
for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
QualType T = getFunctionOrMethodArgType(d, I).getNonReferenceType();
PossibleTransparentUnionPointerType(T);
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?

21
clang/test/Sema/nonnull.c Normal file
View File

@ -0,0 +1,21 @@
// RUN: %clang_cc1 -fsyntax-only %s
// rdar://9584012
typedef struct {
char *str;
} Class;
typedef union {
Class *object;
} Instance __attribute__((transparent_union));
__attribute__((nonnull(1))) void Class_init(Instance this, char *str) {
this.object->str = str;
}
int main(void) {
Class *obj;
Class_init(0, "Hello World"); // expected-warning {{null passed to a callee which requires a non-null argument}}
Class_init(obj, "Hello World");
}