diff options
author | Ted Kremenek <kremenek@apple.com> | 2014-01-20 05:50:47 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2014-01-20 05:50:47 +0000 |
commit | dbf62e3eee51c0532da044a903ee48fe02b6f63e (patch) | |
tree | 9557e3b68edcd929b93230af5c01cafbe0002720 /clang/lib/Sema/SemaDeclAttr.cpp | |
parent | b5867121a77659eae7958e2cfaeea314f3d14b09 (diff) | |
download | bcm5719-llvm-dbf62e3eee51c0532da044a903ee48fe02b6f63e.tar.gz bcm5719-llvm-dbf62e3eee51c0532da044a903ee48fe02b6f63e.zip |
Wire up basic parser/sema support for attribute 'returns_nonnull'.
This attribute is supported by GCC. More generally it should
probably be a type attribute, but this behavior matches 'nonnull'.
This patch does not include warning logic for checking if a null
value is returned from a function annotated with this attribute.
That will come in subsequent patches.
llvm-svn: 199626
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index eaad404666e..ed8610cec39 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1157,12 +1157,14 @@ static void possibleTransparentUnionPointerType(QualType &T) { } static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr, - SourceRange R) { + SourceRange R, bool isReturnValue = false) { T = T.getNonReferenceType(); possibleTransparentUnionPointerType(T); if (!T->isAnyPointerType() && !T->isBlockPointerType()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only) + S.Diag(Attr.getLoc(), + isReturnValue ? diag::warn_attribute_return_pointers_only + : diag::warn_attribute_pointers_only) << Attr.getName() << R; return false; } @@ -1231,6 +1233,23 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static void handleReturnsNonNullAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + QualType ResultType; + if (const FunctionType *Ty = D->getFunctionType()) + ResultType = Ty->getResultType(); + else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) + ResultType = MD->getResultType(); + + if (!attrNonNullArgCheck(S, ResultType, Attr, Attr.getRange(), + /* isReturnValue */ true)) + return; + + D->addAttr(::new (S.Context) + ReturnsNonNullAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + static const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) { switch (K) { case OwnershipAttr::Holds: return "'ownership_holds'"; @@ -3978,6 +3997,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, else handleNonNullAttr(S, D, Attr); break; + case AttributeList::AT_ReturnsNonNull: + handleReturnsNonNullAttr(S, D, Attr); + break; case AttributeList::AT_Overloadable: handleSimpleAttribute<OverloadableAttr>(S, D, Attr); break; case AttributeList::AT_Ownership: handleOwnershipAttr (S, D, Attr); break; |