summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2014-01-17 06:24:56 +0000
committerTed Kremenek <kremenek@apple.com>2014-01-17 06:24:56 +0000
commit9aedc159ef4ccbacec1c77e0a425eb0f62bcf4f5 (patch)
treecc6d26c5454642c978f0f64bd5284fe049067b47 /clang/lib/Sema/SemaDeclAttr.cpp
parent07e4a66306af396f068cdae30c872037147a1824 (diff)
downloadbcm5719-llvm-9aedc159ef4ccbacec1c77e0a425eb0f62bcf4f5.tar.gz
bcm5719-llvm-9aedc159ef4ccbacec1c77e0a425eb0f62bcf4f5.zip
Enhance attribute 'nonnull' to be applicable to parameters directly (infix).
This allows the following syntax: void baz(__attribute__((nonnull)) const char *str); instead of: void baz(const char *str) __attribute__((nonnull(1))); This also extends to Objective-C methods. The checking logic in Sema is not as clean as I would like. Effectively now we need to check both the FunctionDecl/ObjCMethodDecl and the parameters, so the point of truth is spread in two places, but the logic isn't that cumbersome. Implements <rdar://problem/14691443>. llvm-svn: 199467
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp48
1 files changed, 39 insertions, 9 deletions
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