diff options
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; |