r219625 - [analyzer] Check all 'nonnull' attributes, not just the first one.

Jordan Rose jordan_rose at apple.com
Mon Oct 13 12:38:03 PDT 2014


Author: jrose
Date: Mon Oct 13 14:38:02 2014
New Revision: 219625

URL: http://llvm.org/viewvc/llvm-project?rev=219625&view=rev
Log:
[analyzer] Check all 'nonnull' attributes, not just the first one.

Patch by Daniel Fahlgren!

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
    cfe/trunk/test/Analysis/nonnull.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp?rev=219625&r1=219624&r2=219625&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp Mon Oct 13 14:38:02 2014
@@ -49,16 +49,27 @@ void NonNullParamChecker::checkPreCall(c
   if (!FD)
     return;
 
-  // FIXME: This is wrong; there can be multiple attributes with different sets
-  // of non-null parameter indices.
-  const NonNullAttr *Att = FD->getAttr<NonNullAttr>();
+  // Merge all non-null attributes
+  unsigned NumArgs = Call.getNumArgs();
+  llvm::SmallBitVector AttrNonNull(NumArgs);
+  for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
+    if (!NonNull->args_size()) {
+      AttrNonNull.set(0, NumArgs);
+      break;
+    }
+    for (unsigned Val : NonNull->args()) {
+      if (Val >= NumArgs)
+        continue;
+      AttrNonNull.set(Val);
+    }
+  }
 
   ProgramStateRef state = C.getState();
 
   CallEvent::param_type_iterator TyI = Call.param_type_begin(),
                                  TyE = Call.param_type_end();
 
-  for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx){
+  for (unsigned idx = 0; idx < NumArgs; ++idx) {
 
     // Check if the parameter is a reference. We want to report when reference
     // to a null pointer is passed as a paramter.
@@ -68,7 +79,7 @@ void NonNullParamChecker::checkPreCall(c
       TyI++;
     }
 
-    bool haveAttrNonNull = Att && Att->isNonNull(idx);
+    bool haveAttrNonNull = AttrNonNull[idx];
     if (!haveAttrNonNull) {
       // Check if the parameter is also marked 'nonnull'.
       ArrayRef<ParmVarDecl*> parms = Call.parameters();

Modified: cfe/trunk/test/Analysis/nonnull.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nonnull.m?rev=219625&r1=219624&r2=219625&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/nonnull.m (original)
+++ cfe/trunk/test/Analysis/nonnull.m Mon Oct 13 14:38:02 2014
@@ -76,6 +76,104 @@ int rdar16153464(union rdar16153464_full
   rdar16153464_check(0); // expected-warning{{nonnull}}
 }
 
+// Multiple attributes, the basic case
+void multipleAttributes_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(2)));
+
+void testMultiple_1(void) {
+  char c;
+  multipleAttributes_1(&c, &c); // no-warning
+}
+
+void testMultiple_2(void) {
+  char c;
+  multipleAttributes_1(0, &c); // expected-warning{{nonnull}}
+}
+
+void testMultiple_3(void) {
+  char c;
+  multipleAttributes_1(&c, 0); // expected-warning{{nonnull}}
+}
+
+void testMultiple_4(void) {
+  multipleAttributes_1(0, 0);// expected-warning{{nonnull}}
+}
+
+// Multiple attributes, multiple prototypes
+void multipleAttributes_2(char *p, char *q) __attribute((nonnull(1)));
+void multipleAttributes_2(char *p, char *q) __attribute((nonnull(2)));
+
+void testMultiple_5(void) {
+  char c;
+  multipleAttributes_2(0, &c);// expected-warning{{nonnull}}
+}
+
+void testMultiple_6(void) {
+  char c;
+  multipleAttributes_2(&c, 0);// expected-warning{{nonnull}}
+}
+
+void testMultiple_7(void) {
+  multipleAttributes_2(0, 0);// expected-warning{{nonnull}}
+}
+
+// Multiple attributes, same index
+void multipleAttributes_3(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull(1)));
+
+void testMultiple_8(void) {
+  char c;
+  multipleAttributes_3(0, &c); // expected-warning{{nonnull}}
+}
+
+void testMultiple_9(void) {
+  char c;
+  multipleAttributes_3(&c, 0); // no-warning
+}
+
+// Multiple attributes, the middle argument is missing an attribute
+void multipleAttributes_4(char *p, char *q, char *r) __attribute((nonnull(1))) __attribute((nonnull(3)));
+
+void testMultiple_10(void) {
+  char c;
+  multipleAttributes_4(0, &c, &c); // expected-warning{{nonnull}}
+}
+
+void testMultiple_11(void) {
+  char c;
+  multipleAttributes_4(&c, 0, &c); // no-warning
+}
+
+void testMultiple_12(void) {
+  char c;
+  multipleAttributes_4(&c, &c, 0); // expected-warning{{nonnull}}
+}
+
+
+// Multiple attributes, when the last is without index
+void multipleAttributes_all_1(char *p, char *q) __attribute((nonnull(1))) __attribute((nonnull));
+
+void testMultiple_13(void) {
+  char c;
+  multipleAttributes_all_1(0, &c); // expected-warning{{nonnull}}
+}
+
+void testMultiple_14(void) {
+  char c;
+  multipleAttributes_all_1(&c, 0); // expected-warning{{nonnull}}
+}
+
+// Multiple attributes, when the first is without index
+void multipleAttributes_all_2(char *p, char *q) __attribute((nonnull)) __attribute((nonnull(2)));
+
+void testMultiple_15(void) {
+  char c;
+  multipleAttributes_all_2(0, &c); // expected-warning{{nonnull}}
+}
+
+void testMultiple_16(void) {
+  char c;
+  multipleAttributes_all_2(&c, 0); // expected-warning{{nonnull}}
+}
+
 void testVararg(int k, void *p) {
   extern void testVararg_check(int, ...) __attribute__((nonnull));
   void *n = 0;





More information about the cfe-commits mailing list