diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-08-01 12:58:11 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-08-01 12:58:11 +0000 |
commit | 4bfa0de5b07d3d104e3c14a550cf5c354ffc3739 (patch) | |
tree | 70eb606ad0ffdf92237ed9cd95461d1df93350aa /clang/lib | |
parent | 78e83d8895384096a8dfca0c2b3b3d7ae5282811 (diff) | |
download | bcm5719-llvm-4bfa0de5b07d3d104e3c14a550cf5c354ffc3739.tar.gz bcm5719-llvm-4bfa0de5b07d3d104e3c14a550cf5c354ffc3739.zip |
Improving diagnostic source ranges for the nonnull attribute. Now it highlights the attribute and the faulty nonpointer type when possible.
llvm-svn: 214507
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 40 |
2 files changed, 38 insertions, 9 deletions
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 2204dff1373..4657cf371b2 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/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<const ObjCMethodDecl *> &Methods, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ff4192e91d3..663c80c129c 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -88,12 +88,30 @@ static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) { return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType(); } +static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getParamDecl(Idx)->getSourceRange(); + else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) + return MD->parameters()[Idx]->getSourceRange(); + else if (const auto *BD = dyn_cast<BlockDecl>(D)) + return BD->getParamDecl(Idx)->getSourceRange(); + return SourceRange(); +} + static QualType getFunctionOrMethodResultType(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) return cast<FunctionType>(FnTy)->getReturnType(); return cast<ObjCMethodDecl>(D)->getReturnType(); } +static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getReturnTypeSourceRange(); + else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) + return MD->getReturnTypeSourceRange(); + return SourceRange(); +} + static bool isFunctionOrMethodVariadic(const Decl *D) { if (const FunctionType *FnTy = D->getFunctionType()) { const FunctionProtoType *proto = cast<FunctionProtoType>(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; |