[cfe-dev] NonNull attribute, bug report. (Or misunderstanding)
Ted Kremenek
kremenek at apple.com
Thu Dec 4 11:15:12 PST 2008
Incidentally, I do think there is a clang bug here in how we process
the nonnull attribute. I'm writing a few more test cases for the
analyzer to identify the issue.
On Dec 4, 2008, at 10:39 AM, Ted Kremenek wrote:
>
> On Dec 4, 2008, at 4:27 AM, Paolo Bolzoni wrote:
>
>> Simple declaration:
>> extern void* my_memcpy (void *dest, const void *src, unsigned long
>> len)
>> __attribute__((nonnull (1, 2)));
>>
>>
>>
>> The relative AST vertex do have the clang::Attr pointer. But this
>> simple loop
>> outputs nothing:
>>
>> my_decl is a clang::FunctionDecl* relative to the function
>> declaration.
>> non_null_attribute is a clang::NonNullAttr* relative to the non
>> null attribute
>> of my_decl.
>>
>> for (unsigned int e = my_decl-> getNumParams(), b = 1; b <= e; ++b) {
>> if (non_null_attribute-> isNonNull(b)) {
>> std::cout << "Yes, parameter " << b << "is non-null!" <<
>> std::endl;
>> }
>> }
>>
>> What am I doing wrong? Or there indeed is a clang bug somewhere?
>
> Hi Paolo,
>
> You should use a zero-indexed numbering of the attributes. '1' and
> '2' getting converted internally to '0' and '1' to match with the
> indexing of parameters in the ASTs.
>
> It may also be instructive to look at how the static analyzer
> consults this attribute (this is in GRExprEngineInternalChecks.cpp):
>
> FunctionDecl* FD =
> dyn_cast<FunctionDecl>(cast<loc::FuncVal>(X).getDecl());
> const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
>
> if (!Att)
> return false;
>
> // Iterate through the arguments of CE and check them for null.
>
> unsigned idx = 0;
> bool hasError = false;
>
> for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!
> =E;
> ++I, ++idx) {
>
> if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
> continue;
>
> RangedBugReport R(BT, N);
> R.addRange((*I)->getSourceRange());
> Reports.push_back(R);
> hasError = true;
> }
>
> Since this code is so similar to yours, I'm a little confused why
> you don't get even one "Yes, parameter X is non-null" anywhere. One
> thing worth verifying is that 'e' is non-zero (i.e., is the look
> ever entered). Inserting breakpoints in gdb would be my next step.
>
> There is also a test case for the static analyzer in test/Analysis
> that might be useful to compare against:
>
> $ cd test/Analysis
> $ clang -checker-simple null-deref-ps.c
> ...
> ANALYZE: null-deref-ps.c f6
> null-deref-ps.c:64:15: 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}}
> ^ ~
> ANALYZE: null-deref-ps.c f6b
> null-deref-ps.c:71:15: warning: Null pointer passed as an argument
> to a 'nonnull' parameter
> return !p ? bar2(p, 1) // expected-warning {{Null pointer passed as
> an argument to a 'nonnull' parameter}}
> ^ ~
> ...
More information about the cfe-dev
mailing list