[PATCH] c++/60760 - arithmetic on null pointers should not be allowed in constant expressions

Martin Sebor msebor@gmail.com
Wed Jul 20 18:15:00 GMT 2016


On 07/20/2016 07:52 AM, Jason Merrill wrote:
> On Mon, Jul 18, 2016 at 6:15 PM, Martin Sebor <msebor@gmail.com> wrote:
>> On 07/18/2016 11:51 AM, Jason Merrill wrote:
>>>
>>> On 07/06/2016 06:20 PM, Martin Sebor wrote:
>>>>
>>>> @@ -2911,6 +2923,14 @@ cxx_eval_indirect_ref (const constexpr_ctx
>>>> *ctx, tree t,
>>>>         if (*non_constant_p)
>>>>       return t;
>>>>
>>>> +      if (integer_zerop (op0))
>>>> +    {
>>>> +      if (!ctx->quiet)
>>>> +        error ("dereferencing a null pointer");
>>>> +      *non_constant_p = true;
>>>> +      return t;
>>>> +    }
>>>
>>> I'm skeptical of checking this here, since *p is valid for null p; &*p
>>> is even a constant expression.  And removing this hunk doesn't seem to
>>> break any of your tests.
>>>
>>> OK with that hunk removed.
>>
>> With it removed the constexpr-nullptr-2.C test fails on line 64:
>>
>>    constexpr const int *pi0 = &pa2->pa1->pa0->i;   // { dg-error "null
>> pointer|not a constant" }
>>
>> Here, pa2 and pa1 are non-null but pa0 is null.
>
> It doesn't fail for me; that line hits the error in
> cxx_eval_component_reference.  I'm only talking about removing the
> cxx_eval_indirect_ref hunk.

Sorry, I may have been referring to an older patch.  With the latest
patch, the assertion is on line 75.  It's also not failing, even
though it should be.  The problem is that I had misunderstood how
the vertical bar in DejaGnu directives works.  I thought it meant
that both sides had to match a message on that line, when it means
only one side has to.  I'll need to fix that (how does one match
two messages on the same line?)

But removing the hunk as you suggest does break the intent of the
test.  With it there, we get a descriptive message for the invalid
code below clearly explaining the problem:

$ cat xyz.c && /build/gcc-60760/gcc/xgcc -B /build/gcc-60760/gcc -S 
-Wall -Wextra -Wpedantic -xc++ xyz.c
struct S { const S *p; int i; };

constexpr S s0 = { 0, 0 };
constexpr S s1 = { &s0, 1 };

constexpr int i = s1.p->p->i;
xyz.c:6:28: error: dereferencing a null pointer
  constexpr int i = s1.p->p->i;
                             ^

With the hunk removed, all we get is the generic:

xyz.c:6:28: error: ‘*(const S*)((const S*)s1.S::p)->S::p’ is not a 
constant expression
  constexpr int i = s1.p->p->i;
                             ^

Re-reading your comment above now: "since *p is valid for null p;"
I agree that &*p is valid when p is null.  Unless I missed a case
it is accepted with or without the hunk.  Otherwise, *p is not valid,
and it is also rejected with or without it.

Is there something else you're worried about with the hunk that
makes you want to trade it off for the less informative message?

Martin



More information about the Gcc-patches mailing list