summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-08-01 12:58:11 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-08-01 12:58:11 +0000
commit4bfa0de5b07d3d104e3c14a550cf5c354ffc3739 (patch)
tree70eb606ad0ffdf92237ed9cd95461d1df93350aa /clang/lib
parent78e83d8895384096a8dfca0c2b3b3d7ae5282811 (diff)
downloadbcm5719-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.cpp7
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp40
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;
OpenPOWER on IntegriCloud