On 3/1/21 12:10 PM, Martin Sebor wrote:
On 2/24/21 8:13 PM, Jason Merrill wrote:
On 2/24/21 5:25 PM, Martin Sebor wrote:
In r11-6900 (PR 98646 - static_cast confuses -Wnonnull) we decided
that issuing -Wnonnull for dereferencing the result of dynamic_cast
was helpful despite the false positives it causes when the pointer
is guaranteed not to be null because of a prior test.
The test case in PR 99251 along with the feedback I got from Martin
Liska have convinced me it was not the right decision.
The attached patch arranges for dynamic_cast to also suppress -Wnonnull
analogously to static_cast. Since there already is a helper function
that builds the if-not-null test (ifnonnull) and sets TREE_NO_WARNING,
I factored out the corresponding code from build_base_path that sets
the additional TREE_NO_WARNING bit for static_cast into the function
and called it from both places. I also renamed the function to make
its purpose clearer and for consistency with other build_xxx APIs.
Let's call it build_if_nonnull, as it builds the COND_EXPR as well as
the test.
Done.
+ /* The dynamic_cast might fail but so a warning might be justified
+ but not when the operand is guarded. See pr99251. */
+ if (B *q = p->bptr ())
+ dynamic_cast<C*>(q)->g (); // { dg-bogus
"\\\[-Wnonnull" }
This guard is no more necessary than it is for static_cast; both cases
deal with null arguments. Let's not add these checks to the testcases.
Done.
This guard doesn't check for the mentioned case of dynamic_cast
failing because the B* does not in fact point to a C.
I think we can just change the dg-warning to dg-bogus. Sure,
dynamic_cast might fail, but AFAICT -Wnonnull isn't supposed to warn
about arguments that *might* be null, only arguments that are *known*
to be null.
Done.
I had added the 'if' to the test to make it clear why the warning
isn't expected. I replaced it with a comment to that effect.
FWIW, I do think a warning for dynamic_cast to a pointer would be
helpful in the absence of an if statement in these cases:
void f (B *p)
{
dynamic_cast<D*>(p)->g ();
}
Not because p may be null but because the result of the cast may be
for a nonnull p. If it's f's precondition that D is derived from B
(in addition to p being nonnull) the cast would be better written as
one to a reference to D.
Agreed, or if it isn't a precondition,
if (D* dp = dynamic_cast<D*>(p))
dp->g();
Such a warning would need to be issued by the middle end and although
it could be controlled by a new option (say -Wdynamic-cast, along with
the cases discussed in PR 12277)
Sounds good.
I don't think issuing -Wnonnull in this case would be inappropriate.
I disagree; issuing -Wnonnull for this case would be wrong. Again,
-Wnonnull is supposed to warn when an argument *is* null, not when it
*might* be null.
I think warning about this case is a good idea, just not as part of
-Wnonnull.
Anyway, that's something to consider for GCC 12. For now, please see
the revised patch.
* rtti.c (ifnonnull): Rename...
(build_nonnull_test): ...to this. Set no-warning bit on COND_EXPR.
The ChangeLog needs updating.
+ /* Unlike static_cast, dynamic cast may fail for a nonnull operand but
Yes, but...
+ since the front end can't see if the cast is guarded against being
+ invoked with a null
No; my point was that whether the cast is guarded against being invoked
with a null is no more relevant for dynamic_cast than it is for
static_cast, as both casts give a null result for a null argument.
For this test, dynamic_cast is not significantly different from
static_cast. For both casts, the bug was the compiler warning about a
nullptr that it introduced itself.
verify there's no warning. See also pr99251. */
Yes.
- dynamic_cast<const C*>(p->bptr ())->g (); // { dg-warning "\\\[-Wnonnull" }
+ dynamic_cast<const C*>(p)->g (); // { dg-bogus "\\\[-Wnonnull" }
Please put back the ->bptr()s.
Jason