This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/79961] Should diagnose when '__nonnull__' attribute is applied to implicit this argument


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79961

--- Comment #10 from Martin Sebor <msebor at gcc dot gnu.org> ---
All the interesting calls here are undefined.

The point of the example is to highlight that the nonnull attribute on the
typedef

  typedef void F (void*) __attribute__ ((__nonnull__ (1)));

is interpreted differently depending on how the typedef is used.  While in most
cases the number refers to the first void* argument, when it's used to declare
a member function it refers to the implicit this argument.  If
attribute((nonnull(1))) is to be rejected on non-static member function
declarations as you suggest this seems like a case worth keeping in mind.

The call to A::g in the test case is meant to demonstrate that simply printing
"null argument where non-null required (argument 1)" in the diagnostic may not
be sufficient to identify which argument is being referred to.  The fact that
the caret doesn't point at the argument only makes it that much more difficult
(and underscores the importance of referring to the argument more clearly,
e.g., by printing "the this pointer" instead of "argument 1" or something like
that).

Here's a slightly different example that should make that clear:

$ cat t.C && gcc -O2 -S -Wall -Wextra -Wpedantic t.C
typedef void F (void*, void*) __attribute__ ((nonnull));

struct A {
  F f;
  static F g;
};

void foo (A *p, A *q, A *r)
{
  p->f (q, r);   // argument 1 is the implicit this here...
  r->g (p, r);   // ...but the first argument here
}

void bar ()
{
  A *a = 0, b, c;
  foo (a, &b, &c);
}
t.C: In function ‘void bar()’:
t.C:10:8: warning: argument 1 null where non-null expected [-Wnonnull]
   p->f (q, r);   // argument 1 is the implicit this here...
   ~~~~~^~~~~~
t.C:4:5: note: in a call to function ‘void A::f(void*, void*)’ declared here
   F f;
     ^
t.C:11:8: warning: argument 1 null where non-null expected [-Wnonnull]
   r->g (p, r);   // ...but the first argument here
   ~~~~~^~~~~~
t.C:5:12: note: in a call to function ‘static void A::g(void*, void*)’ declared
here
   static F g;
            ^

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]