On 06/01/2016 02:44 PM, Martin Sebor wrote:
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;

Note that this falls under core issue 1530, which has not been resolved.

I don't quite see the relevance of this issue.  It's concerned
with storage in which an object will exist at some point in
the future when its lifetime begins or where it existed in
the past before its lifetime ended.  There is no object or
storage at s.s above because s.s is null.

True. Unfortunately there isn't any wording about what you can do with the result of indirecting a null pointer or pointer to one-past-the-end of an array. There was some proposed for issue 232, but that hasn't been a high priority. What do you see in the standard currently that makes it undefined?

It might perhaps be okay to accept the expression above as
an extension with the rationale that the offset of the first
member is zero and so its address must be a null pointer, but
it surely wouldn't be okay in the modified test case below
where the second member's offset is non-zero and there may
not be a way to represent that offset as a pointer.

Why not?  It would be a pointer to address 4 or whatever.

Thanks for the hint.  I've made that change and also adjusted
the rest of the patch to avoid passing the nullptr_p around.
It was surprisingly simpler to do than I remembered from my
first attempt back in March.

+  if (code == POINTER_PLUS_EXPR && !*non_constant_p
+      && tree_int_cst_equal (lhs, null_pointer_node))
+    {
+      if (!ctx->quiet)
+        error ("arithmetic involving a null pointer in %qE", lhs);
+      return t;
+    }

+  if (TREE_CODE (whole) == INDIRECT_REF
+      && integer_zerop (TREE_OPERAND (whole, 0))
+      && !ctx->quiet)
+    error ("dereferencing a null pointer in %qE", orig_whole);

+      if (TREE_CODE (t) == INTEGER_CST
+          && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
+          && !integer_zerop (t))
+        {
+          if (!ctx->quiet)
+            error ("arithmetic involving a null pointer in %qE", t);
+        }

These places should all set *non_constant_p, and the second should return t after doing so. OK with that change.

Jason

Reply via email to