From: Aaron Ballman Date: Fri, 1 Aug 2014 12:58:11 +0000 (+0000) Subject: Improving diagnostic source ranges for the nonnull attribute. Now it highlights the... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=502d3d9afcd3e8e3a330bde3076fb1b664e3a9cc;p=clang Improving diagnostic source ranges for the nonnull attribute. Now it highlights the attribute and the faulty nonpointer type when possible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214507 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index db3b084938..13b79fd2ee 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -329,6 +329,7 @@ public: QualType getReturnType() const { return MethodDeclType; } void setReturnType(QualType T) { MethodDeclType = T; } + SourceRange getReturnTypeSourceRange() const; /// \brief Determine the type of an expression that sends a message to this /// function. diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 2204dff137..4657cf371b 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -952,6 +952,13 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { llvm_unreachable("unknown method context"); } +SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const { + const auto *TSI = getReturnTypeSourceInfo(); + if (TSI) + return TSI->getTypeLoc().getSourceRange(); + return SourceRange(); +} + static void CollectOverriddenMethodsRecurse(const ObjCContainerDecl *Container, const ObjCMethodDecl *Method, SmallVectorImpl &Methods, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index ff4192e91d..663c80c129 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -88,12 +88,30 @@ static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) { return cast(D)->parameters()[Idx]->getType(); } +static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) { + if (const auto *FD = dyn_cast(D)) + return FD->getParamDecl(Idx)->getSourceRange(); + else if (const auto *MD = dyn_cast(D)) + return MD->parameters()[Idx]->getSourceRange(); + else if (const auto *BD = dyn_cast(D)) + return BD->getParamDecl(Idx)->getSourceRange(); + return SourceRange(); +} + static QualType getFunctionOrMethodResultType(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) return cast(FnTy)->getReturnType(); return cast(D)->getReturnType(); } +static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) { + if (const auto *FD = dyn_cast(D)) + return FD->getReturnTypeSourceRange(); + else if (const auto *MD = dyn_cast(D)) + return MD->getReturnTypeSourceRange(); + return SourceRange(); +} + static bool isFunctionOrMethodVariadic(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) { const FunctionProtoType *proto = cast(FnTy); @@ -1122,15 +1140,17 @@ static void possibleTransparentUnionPointerType(QualType &T) { } static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr, - SourceRange R, bool isReturnValue = false) { + SourceRange AttrParmRange, + SourceRange NonNullTypeRange, + bool isReturnValue = false) { T = T.getNonReferenceType(); possibleTransparentUnionPointerType(T); if (!T->isAnyPointerType() && !T->isBlockPointerType()) { - S.Diag(Attr.getLoc(), - isReturnValue ? diag::warn_attribute_return_pointers_only - : diag::warn_attribute_pointers_only) - << Attr.getName() << R; + S.Diag(Attr.getLoc(), isReturnValue + ? diag::warn_attribute_return_pointers_only + : diag::warn_attribute_pointers_only) + << Attr.getName() << AttrParmRange << NonNullTypeRange; return false; } return true; @@ -1145,9 +1165,9 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; // Is the function argument a pointer type? - // FIXME: Should also highlight argument in decl in the diagnostic. if (!attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr, - Ex->getSourceRange())) + Ex->getSourceRange(), + getFunctionOrMethodParamRange(D, Idx))) continue; NonNullArgs.push_back(Idx); @@ -1194,7 +1214,8 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, } // Is the argument a pointer type? - if (!attrNonNullArgCheck(S, D->getType(), Attr, D->getSourceRange())) + if (!attrNonNullArgCheck(S, D->getType(), Attr, SourceRange(), + D->getSourceRange())) return; D->addAttr(::new (S.Context) @@ -1205,7 +1226,8 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, static void handleReturnsNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { QualType ResultType = getFunctionOrMethodResultType(D); - if (!attrNonNullArgCheck(S, ResultType, Attr, Attr.getRange(), + SourceRange SR = getFunctionOrMethodResultSourceRange(D); + if (!attrNonNullArgCheck(S, ResultType, Attr, SourceRange(), SR, /* isReturnValue */ true)) return;