Commit 207bf485 by Joseph Myers Committed by Joseph Myers

re PR c/461 (non-lvalue arrays)

	* c-common.c (c_expand_expr_stmt): Apply default conversions to
	non-lvalue arrays if C99.
	* c-typeck.c (default_conversion): Split out code handling
	array-to-pointer and function-to-pointer conversions into a
	separate default_function_array_conversion function.
	(default_function_array_conversion): New function.  Keep track of
	whether any NON_LVALUE_EXPRs were stripped.  Return non-lvalue
	arrays unchanged outside C99 mode instead of giving an error for
	them.
	(build_component_ref): Use pedantic_non_lvalue when handling
	COMPOUND_EXPR.  Don't handle COND_EXPR specially.
	(convert_arguments): Use default_function_array_conversion.
	(build_unary_op): For ADDR_EXPR, take a flag indicating whether
	non-lvalues are OK.
	(unary_complex_lvalue): Likewise.
	(internal_build_compound_expr): Use
	default_function_array_conversion.  Apply default conversions to
	function in compound expression.
	(build_c_cast, build_modify_expr, digest_init, build_asm_stmt):
	Use default_function_array_conversion.
	* doc/extend.texi: Update documentation of subscripting non-lvalue
	arrays.
	Fixes PR c/461.

testsuite:
	* gcc.dg/c90-array-lval-1.c, gcc.dg/c90-array-lval-2.c,
	gcc.dg/c99-array-lval-1.c, gcc.dg/c99-array-lval-2.c: Remove
	XFAILs.  Adjust expected error texts.
	* gcc.c-torture/compile/20011106-1.c,
	gcc.c-torture/compile/20011106-2.c, gcc.dg/c90-array-lval-3.c,
	gcc.dg/c90-array-lval-4.c, gcc.dg/c90-array-lval-5.c,
	gcc.dg/c99-array-lval-3.c, gcc.dg/c99-array-lval-4.c,
	gcc.dg/c99-array-lval-5.c: New tests.

From-SVN: r46805
parent 25cece2f
2001-11-06 Joseph S. Myers <jsm28@cam.ac.uk>
* c-common.c (c_expand_expr_stmt): Apply default conversions to
non-lvalue arrays if C99.
* c-typeck.c (default_conversion): Split out code handling
array-to-pointer and function-to-pointer conversions into a
separate default_function_array_conversion function.
(default_function_array_conversion): New function. Keep track of
whether any NON_LVALUE_EXPRs were stripped. Return non-lvalue
arrays unchanged outside C99 mode instead of giving an error for
them.
(build_component_ref): Use pedantic_non_lvalue when handling
COMPOUND_EXPR. Don't handle COND_EXPR specially.
(convert_arguments): Use default_function_array_conversion.
(build_unary_op): For ADDR_EXPR, take a flag indicating whether
non-lvalues are OK.
(unary_complex_lvalue): Likewise.
(internal_build_compound_expr): Use
default_function_array_conversion. Apply default conversions to
function in compound expression.
(build_c_cast, build_modify_expr, digest_init, build_asm_stmt):
Use default_function_array_conversion.
* doc/extend.texi: Update documentation of subscripting non-lvalue
arrays.
Fixes PR c/461.
2001-11-05 Zack Weinberg <zack@codesourcery.com>
* aclocal.m4: (AM_WITH_NLS): Don't look at ALL_LINGUAS.
......
......@@ -1181,7 +1181,8 @@ c_expand_expr_stmt (expr)
{
/* Do default conversion if safe and possibly important,
in case within ({...}). */
if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE && lvalue_p (expr))
if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
&& (flag_isoc99 || lvalue_p (expr)))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
expr = default_conversion (expr);
......
......@@ -1540,10 +1540,12 @@ removed.
@cindex arrays, non-lvalue
@cindex subscripting and function values
Subscripting is allowed on arrays that are not lvalues, even though the
unary @samp{&} operator is not. (In ISO C99, both are allowed (though
the array may not be used after the next sequence point), but this ISO
C99 feature is not yet fully supported in GCC@.) For example,
In ISO C99, arrays that are not lvalues still decay to pointers, and
may be subscripted, although they may not be modified or used after
the next sequence point and the unary @samp{&} operator may not be
applied to them. As an extension, GCC allows such arrays to be
subscripted in C89 mode, though otherwise they do not decay to
pointers outside C99 mode. For example,
this is valid in GNU C though not valid in C89:
@example
......
2001-11-06 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c90-array-lval-1.c, gcc.dg/c90-array-lval-2.c,
gcc.dg/c99-array-lval-1.c, gcc.dg/c99-array-lval-2.c: Remove
XFAILs. Adjust expected error texts.
* gcc.c-torture/compile/20011106-1.c,
gcc.c-torture/compile/20011106-2.c, gcc.dg/c90-array-lval-3.c,
gcc.dg/c90-array-lval-4.c, gcc.dg/c90-array-lval-5.c,
gcc.dg/c99-array-lval-3.c, gcc.dg/c99-array-lval-4.c,
gcc.dg/c99-array-lval-5.c: New tests.
2001-11-05 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* gcc.dg/cpp/defined.c: Update.
......
/* Test that functions passed to the comma operator are correctly converted
to pointers. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk>. */
void foo (void);
void (*fp) (void);
char x[sizeof (1, foo) == sizeof (fp) ? 1 : -1];
/* Test the the type of a component of a conditional expression between
two structures is correct. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk>. */
struct s { char c; } a, b;
int c;
char x[sizeof ((c ? a : b).c) == 1 ? 1 : -1];
......@@ -16,6 +16,6 @@ bar (void)
(foo ()).c + 1; /* { dg-bogus "warning" "warning in place of error" } */
}
/* { dg-error "non-lvalue" "array not decaying to lvalue" { target *-*-* } 14 }
{ dg-error "non-lvalue" "array not decaying to lvalue" { target *-*-* } 15 }
{ dg-error "non-lvalue" "array not decaying to lvalue" { target *-*-* } 16 }
{ dg-error "non-lvalue|incompatible" "array not decaying to lvalue" { target *-*-* } 15 }
{ dg-error "non-lvalue|invalid" "array not decaying to lvalue" { target *-*-* } 16 }
*/
......@@ -17,4 +17,4 @@ ASSERT (r, sizeof ((foo ()).c) == 17);
/* The non-lvalue array does not decay to a pointer, so the comma expression
has (non-lvalue) array type.
*/
ASSERT (s, sizeof (0, (foo ()).c) == 17); /* { dg-bogus "array" "bad non-lvalue array handling" { xfail *-*-* } } */
ASSERT (s, sizeof (0, (foo ()).c) == 17); /* { dg-bogus "array" "bad non-lvalue array handling" } */
/* Test for non-lvalue arrays decaying to pointers: in C99 only.
Test various ways of producing non-lvalue arrays. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
struct s { char c[1]; };
struct s a, b, c;
int d;
void
bar (void)
{
char *t;
(d ? b : c).c[0]; /* { dg-bogus "warning" "warning in place of error" } */
(d, b).c[0]; /* { dg-bogus "warning" "warning in place of error" } */
(a = b).c[0]; /* { dg-bogus "warning" "warning in place of error" } */
t = (d ? b : c).c; /* { dg-bogus "warning" "warning in place of error" } */
t = (d, b).c; /* { dg-bogus "warning" "warning in place of error" } */
t = (a = b).c; /* { dg-bogus "warning" "warning in place of error" } */
(d ? b : c).c + 1; /* { dg-bogus "warning" "warning in place of error" } */
(d, b).c + 1; /* { dg-bogus "warning" "warning in place of error" } */
(a = b).c + 1; /* { dg-bogus "warning" "warning in place of error" } */
}
/* { dg-error "non-lvalue" "array not decaying to lvalue" { target *-*-* } 15 }
{ dg-error "non-lvalue" "array not decaying to lvalue" { target *-*-* } 16 }
{ dg-error "non-lvalue" "array not decaying to lvalue" { target *-*-* } 17 }
{ dg-error "non-lvalue|incompatible" "array not decaying to lvalue" { target *-*-* } 18 }
{ dg-error "non-lvalue|incompatible" "array not decaying to lvalue" { target *-*-* } 19 }
{ dg-error "non-lvalue|incompatible" "array not decaying to lvalue" { target *-*-* } 20 }
{ dg-error "non-lvalue|invalid" "array not decaying to lvalue" { target *-*-* } 21 }
{ dg-error "non-lvalue|invalid" "array not decaying to lvalue" { target *-*-* } 22 }
{ dg-error "non-lvalue|invalid" "array not decaying to lvalue" { target *-*-* } 23 }
*/
/* Test for non-lvalue arrays decaying to pointers: in C99 only.
Test various ways of producing non-lvalue arrays. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
struct s { char c[17]; };
struct s x;
struct s a, b, c;
int d;
#define ASSERT(v, a) char v[((a) ? 1 : -1)]
ASSERT (p, sizeof (x.c) == 17);
ASSERT (q, sizeof (0, x.c) == sizeof (char *));
ASSERT (r0, sizeof ((d ? b : c).c) == 17);
ASSERT (r1, sizeof ((d, b).c) == 17);
ASSERT (r2, sizeof ((a = b).c) == 17);
/* The non-lvalue array does not decay to a pointer, so the comma expression
has (non-lvalue) array type.
*/
ASSERT (s0, sizeof (0, (d ? b : c).c) == 17); /* { dg-bogus "array" "bad non-lvalue array handling" } */
ASSERT (s0, sizeof (0, (d, b).c) == 17); /* { dg-bogus "array" "bad non-lvalue array handling" } */
ASSERT (s0, sizeof (0, (a = b).c) == 17); /* { dg-bogus "array" "bad non-lvalue array handling" } */
/* Test for non-lvalue arrays: test that the unary '&' operator is not
allowed on them, for both C90 and C99. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
struct s { char c[1]; };
extern struct s foo (void);
struct s a, b, c;
int d;
void
bar (void)
{
&((foo ()).c); /* { dg-bogus "warning" "warning in place of error" } */
&((d ? b : c).c); /* { dg-bogus "warning" "warning in place of error" } */
&((d, b).c); /* { dg-bogus "warning" "warning in place of error" } */
&((a = b).c); /* { dg-bogus "warning" "warning in place of error" } */
}
/* { dg-error "lvalue" "bad address-of" { target *-*-* } 17 }
{ dg-error "lvalue" "bad address-of" { target *-*-* } 18 }
{ dg-error "lvalue" "bad address-of" { target *-*-* } 19 }
{ dg-error "lvalue" "bad address-of" { target *-*-* } 20 }
*/
......@@ -12,6 +12,6 @@ bar (void)
{
char *t;
(foo ()).c[0]; /* { dg-bogus "non-lvalue" "array not decaying to lvalue" } */
t = (foo ()).c; /* { dg-bogus "non-lvalue" "array not decaying to lvalue" { xfail *-*-* } } */
(foo ()).c + 1; /* { dg-bogus "non-lvalue" "array not decaying to lvalue" { xfail *-*-* } } */
t = (foo ()).c; /* { dg-bogus "non-lvalue" "array not decaying to lvalue" } */
(foo ()).c + 1; /* { dg-bogus "non-lvalue" "array not decaying to lvalue" } */
}
......@@ -15,4 +15,4 @@ ASSERT (p, sizeof (x.c) == 17);
ASSERT (q, sizeof (0, x.c) == sizeof (char *));
ASSERT (r, sizeof ((foo ()).c) == 17);
/* The non-lvalue array decays to a pointer in C99. */
ASSERT (s, sizeof (0, (foo ()).c) == sizeof (char *)); /* { dg-bogus "array" "bad non-lvalue array handling" { xfail *-*-* } } */
ASSERT (s, sizeof (0, (foo ()).c) == sizeof (char *)); /* { dg-bogus "array" "bad non-lvalue array handling" } */
/* Test for non-lvalue arrays decaying to pointers: in C99 only.
Test various ways of producing non-lvalue arrays. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
struct s { char c[1]; };
struct s a, b, c;
int d;
void
bar (void)
{
char *t;
(d ? b : c).c[0];
(d, b).c[0];
(a = b).c[0];
t = (d ? b : c).c;
t = (d, b).c;
t = (a = b).c;
(d ? b : c).c + 1;
(d, b).c + 1;
(a = b).c + 1;
}
/* Test for non-lvalue arrays decaying to pointers: in C99 only.
Test various ways of producing non-lvalue arrays. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
struct s { char c[17]; };
struct s x;
struct s a, b, c;
int d;
#define ASSERT(v, a) char v[((a) ? 1 : -1)]
ASSERT (p, sizeof (x.c) == 17);
ASSERT (q, sizeof (0, x.c) == sizeof (char *));
ASSERT (r0, sizeof ((d ? b : c).c) == 17);
ASSERT (r1, sizeof ((d, b).c) == 17);
ASSERT (r2, sizeof ((a = b).c) == 17);
/* The non-lvalue array decays to a pointer in C99. */
ASSERT (s0, sizeof (0, (d ? b : c).c) == sizeof (char *)); /* { dg-bogus "array" "bad non-lvalue array handling" } */
ASSERT (s0, sizeof (0, (d, b).c) == sizeof (char *)); /* { dg-bogus "array" "bad non-lvalue array handling" } */
ASSERT (s0, sizeof (0, (a = b).c) == sizeof (char *)); /* { dg-bogus "array" "bad non-lvalue array handling" } */
/* Test for non-lvalue arrays: test that the unary '&' operator is not
allowed on them, for both C90 and C99. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
struct s { char c[1]; };
extern struct s foo (void);
struct s a, b, c;
int d;
void
bar (void)
{
&((foo ()).c); /* { dg-bogus "warning" "warning in place of error" } */
&((d ? b : c).c); /* { dg-bogus "warning" "warning in place of error" } */
&((d, b).c); /* { dg-bogus "warning" "warning in place of error" } */
&((a = b).c); /* { dg-bogus "warning" "warning in place of error" } */
}
/* { dg-error "lvalue" "bad address-of" { target *-*-* } 17 }
{ dg-error "lvalue" "bad address-of" { target *-*-* } 18 }
{ dg-error "lvalue" "bad address-of" { target *-*-* } 19 }
{ dg-error "lvalue" "bad address-of" { target *-*-* } 20 }
*/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment