On 05/17/2016 01:44 PM, Jason Merrill wrote:
On 05/12/2016 06:34 PM, Martin Sebor wrote:
Attached is a resubmission of the patch for c++/60760 originally
submitted late in the 6.0 cycle along with a patch for c++/67376.
Since c++/60760 was not a regression, it was decided that it
would be safer to defer the fix until after the 6.1.0 release.

While retesting this patch I was happy to notice that it also
fixes another bug: c++/71091 - constexpr reference bound to a null
pointer dereference accepted.

I'm not sure why we need to track nullptr_p through everything.  Can't
we set *non_constant_p instead in the places where it's problematic, as
in cxx_eval_binary_expression?

That would have certainly been my preference over adding another
argument to a subset of the functions, making their declarations
inconsistent.  Unfortunately, I couldn't come up with a simpler
way to make it work.

FWIW, my first inclination was to make the nullptr_p flag part
of constexpr_ctx and move the other xxx_p arguments there, to
simplify the interface, until I noticed that all the functions
take a const constexpr_ctx*, preventing them to modify it.  It
seemed like too much of a change to fix a bug in stage 3, but
I'd be comfortable making it in stage 1 if you think it's
worthwhile (though my preference would be to do in a separate
commit, after fixing this bug).


I understand that the complication comes because of needing to allow

constexpr int *p = &*(int*)0;

but I don't see how cxx_eval_component_reference could come up with a
constant value for the referent of a null pointer, so we already reject

struct A { int i; };
constexpr A* p = nullptr;
constexpr int i = p->i;

In cxx_eval_indirect_ref, we could check !lval and reject the
constant-expression at that point.

The new code in cxx_eval_component_reference diagnoses the following
problem that's not detected otherwise:

  struct S { const S *s; };

  constexpr S s = { 0 };

  constexpr const void *p = &s.s->s;

Martin

Reply via email to