This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: generalized lvalues -- patch outline


Ziemowit Laski writes:

> Indeed, I now appear to have a mainline mod for C and C++ which allows 
> assignment to lvalue casts for pointer types.  What follows is a 
> high-level synopsis of what I did; if there is interest, I can whip up 
> a full-fledged patch, complete with docs.  Please let me know.

It occurs to me -- can't "lvalue casts" be done in standard GNU C and C++?
Source code changes would be required, but they can probably be done largely
mechanically.

Here are the examples I've got -- they can maybe be cleaned up a bit, but
both of these compile your test cases -Wall-cleanly with GCC 3.4.  (They
take advantage of the GCC extension that type-punning through a union is
defined behavior.)

First, the C++ example, since it's cleaner code:

/* lvalue_cast<> code by Jonathan Lennox <lennox at cs dot columbia dot edu>,
 * placed in the public domain. */

template<class Targ, class Src>
Targ& lvalue_cast(Src& s)
{
  union { Src * s; Targ * t; } u;

  u.s = &s;

  return *u.t; /* GNU Extension */
}


/* Test case by Ziemowit Laski <zlaski at apple dot com> */

#include <stdlib.h>
#define CHECK_IF(expr) if (!(expr)) abort ()

static int global;

void f(int &) { global = 35; }
void f(const int &) { global = 78; }

long long_arr[2];

int main(void) {

 char *p;

 lvalue_cast<long *>(p) = long_arr;
 lvalue_cast<long *>(p)++;
 *(long *)p = -1;
 *p = -2;
 CHECK_IF(p[-1] == 0 && p[0] == -2 && p[1] == -1);

 long x = 0;
 f((int)x);
 CHECK_IF(global == 78);

 return 0;
}
And then the C example:

/* LVALUE_CAST code by Jonathan Lennox <lennox at cs dot columbia dot edu>,
 * placed in the public domain. */

#define LVALUE_CAST(TYPE, OBJ) (*({ \
    union { __typeof__(OBJ) * s; TYPE * t; } u; \
\
    u.s = &OBJ; \
    u.t; /* GNU Extension */\
}))


/* Test case by Ziemowit Laski <zlaski at apple dot com> */

#include <stdlib.h>
#define CHECK_IF(expr) if (!(expr)) abort ()

int main(void) {

 char *p;
 long l;
 short s;

 LVALUE_CAST(long *, p) = &l; /* ok */
 LVALUE_CAST(long *, p)++; /* ok */
 LVALUE_CAST(short, l) = 2; /* Result depends on endianness. */
 LVALUE_CAST(long, s) = 3;  /* Stack clobber; run-time undefined behavior. */

 return 0;
}
You'd have to do a global replace of lvalue casts with the new construct,
but I imagine that's a lot easier to explain to programmers than the strict
details of the new rules.

-- 
Jonathan Lennox
lennox at cs dot columbia dot edu

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]