The program below, which is a slight variation of a program from C99 section 6.5.3.4, contains an execution-time sizeof operator and its argument should thus be evaluated. Nevertheless, "i" in not incremented. I would expect "i=1" to be printed. I get "i=0". (Sun's C compiler seems to do the same thing.) #include <stdio.h> size_t fsize3 (int n) { int i = 0; char b[1][n+3]; // Variable length array. size_t s = sizeof (b[i++]); // Execution time sizeof. printf ("i=%d\n", i); return s; } int main() { size_t size; size = fsize3(10); return 0; }
That's not a bug. The standard says this: 5.3.3 Sizeof [expr.sizeof] 1 The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is not evaluated, or a parenthesized type-id. W.
Actually, this requires more thought. I quoted from the C++ standard, but the bug is for C, and the problem lies here: the code is ----------------- size_t fsize3 (int n) { int i = 0; char b[1][n+3]; // Variable length array. size_t s = sizeof (b[i++]); ----------------- Indeed, b[0] is a VLA (or is it? maybe it's the GNU extension that looks so similar), and for that case, Morton pointed me correctly at 6.5.3.4/2 of the C99 standard, which has a special provision for this: If the type of the operand is a variable length array type, the operand is evaluated; otherwise the operand is not evaluated... Sorry for the confusion, W.
Reproducible on x86 and x86-64.
Not a bug. Sizeof *never* has side effects.
I'm wrong. What a stupid thing to do to the C language. Someone should be smacked.
I have a fix for this.
Subject: Bug 18740 Author: mrs Date: Thu May 18 18:22:12 2006 New Revision: 113888 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=113888 Log: Fix up vla, vm and [*] sematics. PR c/18740 PR c/7948 PR c/25802 * c-tree.h (struct c_arg_info): Add had_vla_unspec. (c_vla_unspec_p): Add. (c_vla_type_p): Add. * c-decl.c (struct c_scope): Add had_vla_unspec. (build_array_declarator): Add support for [*]. (grokdeclarator): Likewise. (grokparms): Likewise. (get_parm_info): Likewise. * c-objc-common.c (c_vla_unspec_p): Likewise. * c-objc-common.h (LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P): Likewise. * c-parser.c (c_parser_typeof_specifier): Evaluate arguments to typeof when argument is a variably modified type not inside sizeof or alignof. (c_parser_direct_declarator_inner): Propagate errors. (c_parser_sizeof_expression): Add support for [*]. * c-typeck.c (c_vla_type_p): Add. (composite_type): Add support for vla compositing. (comptypes_internal): Add support for vla compatibility. (c_expr_sizeof_expr): Evaluate vla arguments. * tree.c (variably_modified_type_p): Update comment for [*]. testsuite: * gcc.dg/c90-arraydecl-1.c: Update for vla, vm [*] fixups. * gcc.dg/vla-4.c: Add. * gcc.dg/vla-5.c: Add. * gcc.dg/vla-6.c: Add. Added: trunk/gcc/testsuite/gcc.dg/vla-4.c trunk/gcc/testsuite/gcc.dg/vla-5.c trunk/gcc/testsuite/gcc.dg/vla-6.c Modified: trunk/gcc/ChangeLog trunk/gcc/c-decl.c trunk/gcc/c-objc-common.c trunk/gcc/c-objc-common.h trunk/gcc/c-parser.c trunk/gcc/c-tree.h trunk/gcc/c-typeck.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.dg/c90-arraydecl-1.c trunk/gcc/tree.c
Fixed for 4.2.