summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp16
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp48
2 files changed, 55 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 714e975e42f..c3acd52a1ab 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -736,6 +736,7 @@ static void CheckNonNullArguments(Sema &S,
const NamedDecl *FDecl,
const Expr * const *ExprArgs,
SourceLocation CallSiteLoc) {
+ // Check the attributes attached to the method/function itself.
for (specific_attr_iterator<NonNullAttr>
I = FDecl->specific_attr_begin<NonNullAttr>(),
E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) {
@@ -747,6 +748,21 @@ static void CheckNonNullArguments(Sema &S,
CheckNonNullArgument(S, ExprArgs[*i], CallSiteLoc);
}
}
+
+ // Check the attributes on the parameters.
+ ArrayRef<ParmVarDecl*> parms;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
+ parms = FD->parameters();
+ else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl))
+ parms = MD->parameters();
+
+ unsigned argIndex = 0;
+ for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
+ I != E; ++I, ++argIndex) {
+ const ParmVarDecl *PVD = *I;
+ if (PVD->hasAttr<NonNullAttr>())
+ CheckNonNullArgument(S, ExprArgs[argIndex], CallSiteLoc);
+ }
}
/// Handles the checks for format strings, non-POD arguments to vararg
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b8116a7e8a6..06290672214 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1156,6 +1156,36 @@ static void possibleTransparentUnionPointerType(QualType &T) {
}
}
+static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
+ SourceRange R) {
+ T = T.getNonReferenceType();
+ possibleTransparentUnionPointerType(T);
+
+ if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
+ << Attr.getName() << R;
+ return false;
+ }
+ return true;
+}
+
+static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
+ const AttributeList &Attr) {
+ // Is the argument a pointer type?
+ if (!attrNonNullArgCheck(S, D->getType(), Attr, D->getSourceRange()))
+ return;
+
+ if (Attr.getNumArgs() > 0) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
+ << D->getSourceRange();
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ NonNullAttr(Attr.getRange(), S.Context, 0, 0,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
SmallVector<unsigned, 8> NonNullArgs;
for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
@@ -1165,15 +1195,10 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
// Is the function argument a pointer type?
- QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
- possibleTransparentUnionPointerType(T);
-
- if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
- // FIXME: Should also highlight argument in decl.
- S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only)
- << Attr.getName() << Ex->getSourceRange();
+ // FIXME: Should also highlight argument in decl in the diagnostic.
+ if (!attrNonNullArgCheck(S, getFunctionOrMethodArgType(D, Idx),
+ Attr, Ex->getSourceRange()))
continue;
- }
NonNullArgs.push_back(Idx);
}
@@ -3947,7 +3972,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break;
case AttributeList::AT_NoCommon:
handleSimpleAttribute<NoCommonAttr>(S, D, Attr); break;
- case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break;
+ case AttributeList::AT_NonNull:
+ if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
+ handleNonNullAttrParameter(S, PVD, Attr);
+ else
+ handleNonNullAttr(S, D, Attr);
+ break;
case AttributeList::AT_Overloadable:
handleSimpleAttribute<OverloadableAttr>(S, D, Attr); break;
case AttributeList::AT_Ownership: handleOwnershipAttr (S, D, Attr); break;
OpenPOWER on IntegriCloud