"type of machine mode does not match type of base type")
DIAG(err_attr_wrong_decl, ERROR,
"'%0' attribute invalid on this declaration, requires typedef or value")
-
+DIAG(warn_attribute_nonnull_no_pointers, WARNING,
+ "'nonnull' attribute applied to function with no pointer arguments")
+
// Clang-Specific Attributes
DIAG(err_attribute_iboutlet_non_ivar, ERROR,
"'iboutlet' attribute can only be applied to instance variables")
// FIXME: Should also highlight argument in decl.
S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only,
"nonnull", Ex->getSourceRange());
- return;
+ continue;
}
NonNullArgs.push_back(x);
}
- if (!NonNullArgs.empty()) {
- unsigned* start = &NonNullArgs[0];
- unsigned size = NonNullArgs.size();
- std::sort(start, start + size);
- d->addAttr(new NonNullAttr(start, size));
+ // If no arguments were specified to __attribute__((nonnull)) then all
+ // pointer arguments have a nonnull attribute.
+ if (NonNullArgs.empty()) {
+ unsigned idx = 0;
+
+ for (FunctionTypeProto::arg_type_iterator
+ I=proto->arg_type_begin(), E=proto->arg_type_end(); I!=E; ++I, ++idx)
+ if ((*I)->isPointerType())
+ NonNullArgs.push_back(idx);
+
+ if (NonNullArgs.empty()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
+ return;
+ }
}
- else
- d->addAttr(new NonNullAttr());
+
+ unsigned* start = &NonNullArgs[0];
+ unsigned size = NonNullArgs.size();
+ std::sort(start, start + size);
+ d->addAttr(new NonNullAttr(start, size));
}
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return s[0]; // no-warning
}
-int bar(int* p) __attribute__((nonnull));
+int bar(int* p, int q) __attribute__((nonnull));
int f6(int *p) {
- return !p ? bar(p) : *p; // expected-warning {{Null pointer passed as an argument to a 'nonnull' parameter}}
-}
+ return !p ? bar(p, 1) // expected-warning {{Null pointer passed as an argument to a 'nonnull' parameter}}
+ : bar(p, 0); // no-warning
+}
int* qux();
// RUN: clang -fsyntax-only -verify %s
-int f1(int x) __attribute__((nonnull));
+int f1(int x) __attribute__((nonnull)); // expected-warning{{'nonnull' attribute applied to function with no pointer arguments}}
int f2(int *x) __attribute__ ((nonnull (1)));
int f3(int *x) __attribute__ ((nonnull (0))); // expected-error {{'nonnull' attribute parameter 1 is out of bounds}}
int f4(int *x, int *y) __attribute__ ((nonnull (1,2)));