From: Ted Kremenek Date: Mon, 1 Sep 2008 19:57:52 +0000 (+0000) Subject: Tidy up sema processing of attribute "nonull": X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7fb43c17eb2b4102f40a80a355629aacd70589ad;p=clang Tidy up sema processing of attribute "nonull": - warn about nonnull being applied to functions with no pointer arguments - continue processing argument list in the attribute when we encounter a non-pointer parameter being marked as nonnull - when no argument list is specified, only mark pointers as nonnull. This fixes PR 2732 and radar 6188814. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55610 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 3510e7dee6..95d2112650 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -692,7 +692,9 @@ DIAG(err_mode_wrong_type, ERROR, "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") diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index f94711e987..eb9888e9a2 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -282,20 +282,32 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { // 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) { diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 92e8daa57e..06f67da45a 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -56,11 +56,12 @@ int f5() { 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(); diff --git a/test/Sema/nonnull.c b/test/Sema/nonnull.c index f8a2a0ed78..9a64ce4320 100644 --- a/test/Sema/nonnull.c +++ b/test/Sema/nonnull.c @@ -1,6 +1,6 @@ // 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)));