]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Exclude calls to variadic lambda stubs from -Wnonnull checking (PR c++/95984).
authorMartin Sebor <msebor@redhat.com>
Mon, 6 Jul 2020 21:23:37 +0000 (15:23 -0600)
committerMartin Sebor <msebor@redhat.com>
Mon, 6 Jul 2020 21:23:37 +0000 (15:23 -0600)
Resolves:
PR c++/95984 - Internal compiler error: Error reporting routines re-entered in -Wnonnull on a variadic lamnda
PR c++/96021 - missing -Wnonnull passing nullptr to a nonnull variadic lambda

gcc/c-family/ChangeLog:

PR c++/95984
* c-common.c (check_function_nonnull): Avoid checking syntesized calls
to stub lambda objects with null this pointer.
(check_nonnull_arg): Handle C++ nullptr.

gcc/cp/ChangeLog:

PR c++/95984
* call.c (build_over_call): Check calls only when tf_warning is set.

gcc/testsuite/ChangeLog:

PR c++/95984
* g++.dg/warn/Wnonnull6.C: New test.

gcc/c-family/c-common.c
gcc/cp/call.c
gcc/testsuite/g++.dg/warn/Wnonnull6.C [new file with mode: 0644]

index aae1ddb6b895c935a59b47b23d71044e919de21b..51ecde69f2d44479b573e0578b3d81059abe4da8 100644 (file)
@@ -5308,12 +5308,26 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray)
   int firstarg = 0;
   if (TREE_CODE (ctx.fntype) == METHOD_TYPE)
     {
+      bool closure = false;
+      if (ctx.fndecl)
+       {
+         /* For certain lambda expressions the C++ front end emits calls
+            that pass a null this pointer as an argument named __closure
+            to the member operator() of empty function.  Detect those
+            and avoid checking them, but proceed to check the remaining
+            arguments.  */
+         tree arg0 = DECL_ARGUMENTS (ctx.fndecl);
+         if (tree arg0name = DECL_NAME (arg0))
+           closure = id_equal (arg0name, "__closure");
+       }
+
       /* In calls to C++ non-static member functions check the this
         pointer regardless of whether the function is declared with
         attribute nonnull.  */
       firstarg = 1;
-      check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[0],
-                                       firstarg);
+      if (!closure)
+       check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[0],
+                                         firstarg);
     }
 
   tree attrs = lookup_attribute ("nonnull", TYPE_ATTRIBUTES (ctx.fntype));
@@ -5503,7 +5517,9 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num)
      happen if the "nonnull" attribute was given without an operand
      list (which means to check every pointer argument).  */
 
-  if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
+  tree paramtype = TREE_TYPE (param);
+  if (TREE_CODE (paramtype) != POINTER_TYPE
+      && TREE_CODE (paramtype) != NULLPTR_TYPE)
     return;
 
   /* Diagnose the simple cases of null arguments.  */
index d8923be1d68bcc016e500c6e2d39e3669ec1f7d3..5341a57298017ffb0fed25740f88efeb68d16691 100644 (file)
@@ -8842,15 +8842,16 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   gcc_assert (j <= nargs);
   nargs = j;
 
-  /* Avoid to do argument-transformation, if warnings for format, and for
-     nonnull are disabled.  Just in case that at least one of them is active
+  /* Avoid performing argument transformation if warnings are disabled.
+     When tf_warning is set and at least one of the warnings is active
      the check_function_arguments function might warn about something.  */
 
   bool warned_p = false;
-  if (warn_nonnull
-      || warn_format
-      || warn_suggest_attribute_format
-      || warn_restrict)
+  if ((complain & tf_warning)
+      && (warn_nonnull
+         || warn_format
+         || warn_suggest_attribute_format
+         || warn_restrict))
     {
       tree *fargs = (!nargs ? argarray
                            : (tree *) alloca (nargs * sizeof (tree)));
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull6.C b/gcc/testsuite/g++.dg/warn/Wnonnull6.C
new file mode 100644 (file)
index 0000000..dae6dd2
--- /dev/null
@@ -0,0 +1,37 @@
+/* PR c++/95984 - Internal compiler error: Error reporting routines re-entered
+   in -Wnonnull on a variadic lamnda
+   PR c++/missing -Wnonnull passing nullptr to a nonnull variadic lambda
+   { dg-do compile { target c++11 } }
+   { dg-options "-Wall" } */
+
+typedef int F (int);
+
+F* pr95984 ()
+{
+  // This also triggered the ICE.
+  return [](auto...) { return 0; };     // { dg-bogus "\\\[-Wnonnull" }
+}
+
+
+__attribute__ ((nonnull)) void f (int, ...);
+void ff ()
+{
+  f (1, nullptr);                       // { dg-warning "\\\[-Wnonnull" }
+}
+
+template <class T> void g (T t)
+{
+  t (1, nullptr);                       // { dg-warning "\\\[-Wnonnull" }
+}
+
+void gg (void)
+{
+  g ([](int, auto...) __attribute__ ((nonnull)) { });
+}
+
+template <class T> __attribute__ ((nonnull)) void h (T);
+
+void hh ()
+{
+  h (nullptr);                          //  { dg-warning "\\\[-Wnonnull" }
+}