[cfe-dev] Clang ignores nonnull attributes on pointer-to-member-function declarations

Tom Honermann thonermann at coverity.com
Mon Jul 13 14:00:32 PDT 2015


On 07/13/2015 03:33 PM, Richard Smith wrote:
> On Mon, Jul 13, 2015 at 10:41 AM, Joerg Sonnenberger
> <joerg at britannica.bec.de <mailto:joerg at britannica.bec.de>> wrote:
>
>     On Mon, Jul 13, 2015 at 11:31:54AM -0400, Tom Honermann wrote:
>     > Clang (3.4-trunk) ignores nonnull attributes on pointer-to-member-function
>     > declarations.
>
>     You are aware that 3.4-trunk is quite old and we are about to start the
>     3.7 release cycle?
>
>
> I read that as "from version 3.4 to trunk"

And that is how I intended it.

> And it's true: clang trunk
> still behaves as described. But I'm a bit confused, because the
> referenced GCC bug report says they made this work:
>
> struct Foo;
> void foo (void (Foo::*) () __attribute__ ((nonnull)));
>
> ... where the attribute would presumably apply to the pointer-to-member,
> and the request is to support this:
>
> void (S::*pmf)(int *p1)
>      __attribute__((nonnull));
>
> ... where the attribute (again, presumably) jumps over the
> pointer-to-member and applies to the pointer parameter? This does not
> seem consistent. What is the actual GCC behavior?

Interesting.  It didn't occur to me that the case in the gcc bug report 
is ambiguous with respect to Clang's support for infix nonnull attributes.

As specified, the attribute is either an infix attribute specifying that 
the pointer-to-member-function parameter value must not be null, or it 
is a non-infix attribute specifying that all of the parameters of the 
target of the pointer-to-member-function must not be null.

I don't think gcc supports infix nonnull attributes, so I believe the 
latter behavior is what is intended.  gcc compiler warnings appear to 
bear this out:

$ cat t.cpp
struct S;
void f1(S *s, void (S::*pmf)(void*) __attribute__ ((nonnull))) {
     (s->*pmf)(0);
}
void f2(S *s) {
     f1(s, 0);
}

$ gcc -c -Wall t.cpp
t.cpp: In function ‘void f1(S*, void (S::*)(void*))’:
t.cpp:3:16: warning: null argument where non-null required (argument 2) 
[-Wnonnull]
      (s->*pmf)(0);
                 ^

Note that there is a warning when passing a null argument with the 
pointer-to-member-function invocation, but not when passing a null 
argument as the pointer-to-member-function value.

Tom.




More information about the cfe-dev mailing list