Hello, This patch fixes fixes an erroneous -Wnonnull warning when calling a constructor declared with __attribute__ ((nonnull (1))). The issue is that a NULL pointer is used as the placeholder object for the "this" parameter of the constructor method call until a target object is determined and substituted for the placeholder object during gimplification. Meanwhile, check_function_arguments is called in build_over_call which notices that there is a NULL pointer argument for a parameter that's been marked nonnull, thus issuing the -Wnonnull warning.
This patch modifies the C++ frontend to use build_dummy_object() instead of a NULL pointer as the placeholder object to a constructor method call. This suppresses the warning issued by check_function_arguments because the object returned by build_dummy_object() is not determined to be a NULL pointer. I bootstrapped and regtested this patch on x86_64-unknown-linux-gnu. PR c++/60764 * call.c (build_user_type_coversion): Use build_dummy_object to create the placeholder object for a constructor method call. (build_special_member_call): Likewise. (build_over_call): Check for the placeholder object with is_dummy_object. (build_new_method_call_1): Likewise. Don't attempt to resolve a dummy object for a constructor method call. --- gcc/cp/call.c | 14 +++++--------- gcc/testsuite/g++.dg/warn/nonnull2.C | 10 ++++++++++ 2 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/nonnull2.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ae0d4ff..ff5c834 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3519,8 +3519,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, { int ctorflags = flags; - first_arg = build_int_cst (build_pointer_type (totype), 0); - first_arg = build_fold_indirect_ref (first_arg); + first_arg = build_dummy_object (totype); /* We should never try to call the abstract or base constructor from here. */ @@ -7096,7 +7095,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a temp or an INIT_EXPR otherwise. */ fa = argarray[0]; - if (integer_zerop (fa)) + if (is_dummy_object (fa)) { if (TREE_CODE (arg) == TARGET_EXPR) return arg; @@ -7434,10 +7433,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args, /* Handle the special case where INSTANCE is NULL_TREE. */ if (name == complete_ctor_identifier && !instance) - { - instance = build_int_cst (build_pointer_type (class_type), 0); - instance = build1 (INDIRECT_REF, class_type, instance); - } + instance = build_dummy_object (class_type); else { if (name == complete_dtor_identifier @@ -7747,8 +7743,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, if (init) { - if (INDIRECT_REF_P (instance) - && integer_zerop (TREE_OPERAND (instance, 0))) + if (is_dummy_object (instance)) return get_target_expr_sfinae (init, complain); init = build2 (INIT_EXPR, TREE_TYPE (instance), instance, init); TREE_SIDE_EFFECTS (init) = true; @@ -7847,6 +7842,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, } if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE + && !DECL_CONSTRUCTOR_P (fn) && is_dummy_object (instance)) { instance = maybe_resolve_dummy (instance); diff --git a/gcc/testsuite/g++.dg/warn/nonnull2.C b/gcc/testsuite/g++.dg/warn/nonnull2.C new file mode 100644 index 0000000..10515a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/nonnull2.C @@ -0,0 +1,10 @@ +// PR c++/60764 +// { dg-options "-Wall" } + +struct foo +{ + foo () __attribute__ ((nonnull (1))); +}; + +const foo &x = foo (); // { dg-bogus "null argument" } +foo y = foo (); // { dg-bogus "null argument" } -- 1.9.1