Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c++ > #370

Re: Defect report: lvalue-to-rvalue conversion on one-past-the-end pointer

From Daniel Krügler<daniel.kruegler@googlemail.com>
Newsgroups comp.std.c++
Subject Re: Defect report: lvalue-to-rvalue conversion on one-past-the-end pointer
Date 2011-11-11 13:03 -0800
Organization A noiseless patient Spider
Message-ID <j9hcs5$4vt$1@dont-email.me> (permalink)
References <55732.10.0.16.53.1320710245.squirrel@webmail.secure.aluminati.net>

Show all headers | View raw


Am 08.11.2011 20:31, schrieb Richard Smith:
>  Hi,
>
>  In C89 and C99, it is not legal to (effectively) perform an lvalue-to-rvalue
>  conversion on a one-past-the-end pointer. C99 TC3 6.5.6/8 says the following
>  about the result of adding a pointer and an integer:
>
>  "If the result points one past the last element of the array object, it
>  shall not be used as the operand of a unary * operator that is evaluated."
>
>  C++ copies the entire paragraph as [expr.add]/5, except for that one sentence.
>  Further, C++11 [basic.compound]/3 says:
>
>  "If an object of type T is located at an address A, a pointer of type cv T*
>  whose value is the address A is said to point to that object, regardless of
>  how the value was obtained. [ Note: For instance, the address one past the end
>  of an array (5.7) would be considered to point to an unrelated object of the
>  arrayÂ’s element type that might be located at that address. There are further
>  restrictions on pointers to objects with dynamic storage duration; see
>  3.7.4.3. — end note ]"
>
>  This seems tantamount to saying that such pointers are legitimate to use, if
>  they happen to point to an object of the right type. Not only is this
>  problematic in theory, it's also problematic in practice -- existing compilers
>  for C++ optimize using the C rules, for instance for alias analysis. Consider
>  the following example:
>
>  #include<cstdint>
>  int main(int argc, char **argv) {
>      long long a[1] = { 10 }, b = 20;
>      if (a + 1 ==&b)
>        a[argc] = argc; // a[1] == *(a+1), which points to b,
>                        // regardless of how the value was obtained
>      else if (&b + 1 == a)
>        a[-argc] = argc; // a[-1] == *(a-1), and a points one past
>                         // the end of b, so this points to b
>      else
>        return 0;
>      return b;
>  }
>
>  Remarkably, when run with argc == 1, this does not appear to have undefined
>  behaviour; clearly it should! When built with many optimizing compilers this
>  code "incorrectly" returns 20.
>
>  In addition, this causes trouble for the [expr.const]/2 restriction that only
>  the active member of a union can have an lvalue-to-rvalue conversion performed
>  on it. Consider:
>
>  struct A {}; struct B {};
>  union U {
>      constexpr U(A, int n) : a(n) {}
>      constexpr U(B, int n) : b(n) {}
>      int a, b;
>  };
>  constexpr U arr[] = { { A(), 0 }, { B(), 0 } };
>  constexpr int *p =&arr[0].a; // ok
>  constexpr int *q = p + 1; // ok, one-past-the-end pointer
>                              // points to arr[1].a and arr[1].b
>  constexpr int r = *q; // does this refer to a non-active member of the union?
>
>  C++ should adopt the C rule, and disallow lvalue-to-rvalue conversions on
>  lvalues which refer to objects outside the subobject from which the lvalue is
>  derived.
>
>  [expr.add]/5 also only allows a one-past-the-end pointer to be formed by
>  adding 1 to a pointer. In particular:
>
>      int xs[2];
>      int *p = xs + 2; // undefined behaviour!
>      int *q = xs + 1 + 1; // ok!
>      int *r = q - 1 - 1; // ok!
>      int *s = q - 2; // undefined behaviour!
>
>  This oddity is inherited from C, but such uses are so overwhelmingly common
>  that they should be permitted.

Forwarded to CWG.

Greetings from Bremen,

Daniel Krügler



-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

Back to comp.std.c++ | Previous | NextPrevious in thread | Find similar


Thread

Defect report: lvalue-to-rvalue conversion on one-past-the-end       pointer "Richard Smith"<richard@metafoo.co.uk> - 2011-11-08 11:31 -0800
  Re: Defect report: lvalue-to-rvalue conversion on one-past-the-end        pointer Daniel Krügler<daniel.kruegler@googlemail.com> - 2011-11-11 13:03 -0800

csiph-web