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

Tom Honermann thonermann at coverity.com
Wed Jul 15 10:31:25 PDT 2015


On 07/13/2015 07:08 PM, Richard Smith wrote:
> On Mon, Jul 13, 2015 at 2:00 PM, Tom Honermann <thonermann at coverity.com
> <mailto:thonermann at coverity.com>> wrote:
>
>     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>
>         <mailto: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.
>
>
> OK, we'll need to figure out how to integrate this into our
> __attribute__((nonnull)) semantics. Please do file that PR so we don't
> forget!

PR filed:
https://llvm.org/bugs/show_bug.cgi?id=24133

In researching this, I also found that Clang's behavior with regard to 
nonnull attributes for parameter declarations has changed over time:

$ cat t.cpp
void f1(void (*pf)(void*) __attribute__((nonnull))) {
     pf(0);
}
void f2() {
     f1(0);
}

# Clang 3.4:
clang -c t.cpp
t.cpp:2:9: warning: null passed to a callee which requires a non-null 
argument [-Wnonnull]
     pf(0);
        ~^
1 warning generated.

# Clang 3.5:
clang -c t.cpp
t.cpp:5:9: warning: null passed to a callee which requires a non-null 
argument [-Wnonnull]
     f1(0);
        ~^
1 warning generated.

# Clang 3.6:
clang -c t.cpp
t.cpp:2:9: warning: null passed to a callee that requires a non-null 
argument [-Wnonnull]
     pf(0);
        ~^
t.cpp:5:9: warning: null passed to a callee that requires a non-null 
argument [-Wnonnull]
     f1(0);
        ~^
2 warnings generated.

Clang 3.4 was consistent with gcc semantics.  Clang 3.5 introduced infix 
nonnull attributes and created an ambiguity that was resolved in favor 
of applying the attribute to the parameter declaration (changing 
behavior from Clang 3.4 and breaking consistency with gcc).  Clang 3.6 
addressed the behavioral deviation by applying the attribute to both the 
parameter declaration and the function type of the parameter.  The Clang 
3.6 behavior seems reasonable to me.

Tom.




More information about the cfe-dev mailing list