Exclude calls to variadic lambda stubs from -Wnonnull checking (PR c++/95984).

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.
This commit is contained in:
Martin Sebor 2020-07-06 15:23:37 -06:00
parent 6e1c9715b3
commit 67a493a0b9
3 changed files with 63 additions and 9 deletions

View 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. */

View 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)));

View file

@ -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" }
}