This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Candidate fix for PR c/7353
On Mon, Oct 07, 2002 at 10:59:31PM -0700, Richard Henderson wrote:
> > produces an ICE with all versions of GCC since 3.0. This is an
> > obscure, rarely-used extension, but if we're going to have it, it
> > should work.
>
> I'm for nuking it myself. If there's not unanimous agreement,
> I guess I'll look at your patch tomorrow.
It's a documented extension, so we might want to deprecate it for a
release before making it go away, but since it's been broken since 3.0
and only one person has complained, I certainly wouldn't object to
killing it immediately.
Here's a patch to eliminate it altogether, so all alternatives will be
on the table. (Note that C++ generates three error messages for the
construct with this patch, which is overkill IMO.)
zw
* c-decl.c (start_decl): It is always an error to write
"typedef T = expr;".
(finish_decl): Remove special case for TYPE_DECL with nonzero INIT.
* cp/decl.c: Likewise.
* doc/extend.texi: Delete documentation of "typedef T = expr;"
extension. Move useful example there to the "typeof" section,
and rewrite it to use that extension instead. Delete silly
typeof example. Change cross-references to "Naming Types" to
refer to "Typeof" instead.
===================================================================
Index: c-decl.c
--- c-decl.c 22 Sep 2002 02:03:14 -0000 1.350
+++ c-decl.c 8 Oct 2002 06:47:21 -0000
@@ -2821,15 +2821,9 @@ start_decl (declarator, declspecs, initi
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- /* typedef foo = bar means give foo the same type as bar.
- We haven't parsed bar yet, so `finish_decl' will fix that up.
- Any other case of an initialization in a TYPE_DECL is an error. */
- if (pedantic || list_length (declspecs) > 1)
- {
- error ("typedef `%s' is initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- initialized = 0;
- }
+ error ("typedef `%s' is initialized",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ initialized = 0;
break;
case FUNCTION_DECL:
@@ -2988,16 +2982,7 @@ finish_decl (decl, init, asmspec_tree)
init = 0;
if (init)
- {
- if (TREE_CODE (decl) != TYPE_DECL)
- store_init_value (decl, init);
- else
- {
- /* typedef foo = bar; store the type of bar as the type of foo. */
- TREE_TYPE (decl) = TREE_TYPE (init);
- DECL_INITIAL (decl) = init = 0;
- }
- }
+ store_init_value (decl, init);
/* Deduce size of array from initialization, if not already known */
if (TREE_CODE (type) == ARRAY_TYPE
===================================================================
Index: cp/decl.c
--- cp/decl.c 2 Oct 2002 18:46:40 -0000 1.942
+++ cp/decl.c 8 Oct 2002 06:53:42 -0000
@@ -7290,14 +7290,8 @@ start_decl (declarator, declspecs, initi
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- /* typedef foo = bar means give foo the same type as bar.
- We haven't parsed bar yet, so `cp_finish_decl' will fix that up.
- Any other case of an initialization in a TYPE_DECL is an error. */
- if (pedantic || list_length (declspecs) > 1)
- {
- error ("typedef `%D' is initialized", decl);
- initialized = 0;
- }
+ error ("typedef `%D' is initialized", decl);
+ initialized = 0;
break;
case FUNCTION_DECL:
@@ -8156,12 +8150,6 @@ cp_finish_decl (decl, init, asmspec_tree
/* Take care of TYPE_DECLs up front. */
if (TREE_CODE (decl) == TYPE_DECL)
{
- if (init && DECL_INITIAL (decl))
- {
- /* typedef foo = bar; store the type of bar as the type of foo. */
- TREE_TYPE (decl) = type = TREE_TYPE (init);
- DECL_INITIAL (decl) = init = NULL_TREE;
- }
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
===================================================================
Index: doc/extend.texi
--- doc/extend.texi 27 Sep 2002 13:30:07 -0000 1.104
+++ doc/extend.texi 8 Oct 2002 06:47:23 -0000
@@ -427,7 +427,6 @@ extensions, accepted by GCC in C89 mode
* Labels as Values:: Getting pointers to labels, and computed gotos.
* Nested Functions:: As in Algol and Pascal, lexical scoping of functions.
* Constructing Calls:: Dispatching a call to another function.
-* Naming Types:: Giving a name to the type of some expression.
* Typeof:: @code{typeof}: referring to the type of an expression.
* Lvalues:: Using @samp{?:}, @samp{,} and casts in lvalues.
* Conditionals:: Omitting the middle operand of a @samp{?:} expression.
@@ -538,8 +537,7 @@ the value of an enumeration constant, th
the initial value of a static variable.
If you don't know the type of the operand, you can still do this, but you
-must use @code{typeof} (@pxref{Typeof}) or type naming (@pxref{Naming
-Types}).
+must use @code{typeof} (@pxref{Typeof}).
Statement expressions are not supported fully in G++, and their fate
there is unclear. (It is possible that they will become fully supported
@@ -888,29 +886,6 @@ the containing function. You should spe
returned by @code{__builtin_apply}.
@end deftypefn
-@node Naming Types
-@section Naming an Expression's Type
-@cindex naming types
-
-You can give a name to the type of an expression using a @code{typedef}
-declaration with an initializer. Here is how to define @var{name} as a
-type name for the type of @var{exp}:
-
-@example
-typedef @var{name} = @var{exp};
-@end example
-
-This is useful in conjunction with the statements-within-expressions
-feature. Here is how the two together can be used to define a safe
-``maximum'' macro that operates on any arithmetic type:
-
-@example
-#define max(a,b) \
- (@{typedef _ta = (a), _tb = (b); \
- _ta _a = (a); _tb _b = (b); \
- _a > _b ? _a : _b; @})
-@end example
-
@cindex underscores in variables in macros
@cindex @samp{_} in variables in macros
@cindex local variables in macros
@@ -962,6 +937,20 @@ A @code{typeof}-construct can be used an
used. For example, you can use it in a declaration, in a cast, or inside
of @code{sizeof} or @code{typeof}.
+@code{typeof} is often useful in conjunction with the
+statements-within-expressions feature. Here is how the two together can
+be used to define a safe ``maximum'' macro that operates on any
+arithmetic type and evaluates each of its arguments exactly once:
+
+@example
+#define max(a,b) \
+ (@{ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a > _b ? _a : _b; @})
+@end example
+
+Some more examples of the use of @code{typeof}:
+
@itemize @bullet
@item
This declares @code{y} with the type of what @code{x} points to.
@@ -976,39 +965,6 @@ This declares @code{y} as an array of su
@example
typeof (*x) y[4];
@end example
-
-@item
-This declares @code{y} as an array of pointers to characters:
-
-@example
-typeof (typeof (char *)[4]) y;
-@end example
-
-@noindent
-It is equivalent to the following traditional C declaration:
-
-@example
-char *y[4];
-@end example
-
-To see the meaning of the declaration using @code{typeof}, and why it
-might be a useful way to write, let's rewrite it with these macros:
-
-@example
-#define pointer(T) typeof(T *)
-#define array(T, N) typeof(T [N])
-@end example
-
-@noindent
-Now the declaration can be rewritten this way:
-
-@example
-array (pointer (char), 4) y;
-@end example
-
-@noindent
-Thus, @code{array (pointer (char), 4)} is the type of arrays of 4
-pointers to @code{char}.
@end itemize
@node Lvalues
@@ -6827,12 +6783,12 @@ the minimum value of variables @var{i} a
However, side effects in @code{X} or @code{Y} may cause unintended
behavior. For example, @code{MIN (i++, j++)} will fail, incrementing
-the smaller counter twice. A GNU C extension allows you to write safe
-macros that avoid this kind of problem (@pxref{Naming Types,,Naming an
-Expression's Type}). However, writing @code{MIN} and @code{MAX} as
-macros also forces you to use function-call notation for a
-fundamental arithmetic operation. Using GNU C++ extensions, you can
-write @w{@samp{int min = i <? j;}} instead.
+the smaller counter twice. The GNU C @code{typeof} extension allows you
+to write safe macros that avoid this kind of problem (@pxref{Typeof}).
+However, writing @code{MIN} and @code{MAX} as macros also forces you to
+use function-call notation for a fundamental arithmetic operation.
+Using GNU C++ extensions, you can write @w{@samp{int min = i <? j;}}
+instead.
Since @code{<?} and @code{>?} are built into the compiler, they properly
handle expressions with side-effects; @w{@samp{int min = i++ <? j++;}}