From: Fariborz Jahanian Date: Mon, 27 Jun 2011 21:12:03 +0000 (+0000) Subject: Handle nonnull attribute with optional argument number on X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=68fe96adf787abd1e98016da0f38e26644faf7b9;p=clang Handle nonnull attribute with optional argument number on functions with arguments of transparent unions type. // rdar://9584012 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133941 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 9302277e13..f5e80d5630 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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()) { + 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()) { - 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? diff --git a/test/Sema/nonnull.c b/test/Sema/nonnull.c new file mode 100644 index 0000000000..cea8e3d0dd --- /dev/null +++ b/test/Sema/nonnull.c @@ -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"); +} +