Commit 928c19bb by Joseph Myers Committed by Joseph Myers

re PR c/456 (constant expressions constraints (gcc.dg/c90-const-expr-1))

	PR c/456
	PR c/5675
	PR c/19976
	PR c/29116
	PR c/31871
	PR c/35198

fixincludes:
	* inclhack.def (glibc_tgmath): New fix.
	* fixincl.x: Regenerate.
	* tests/base/tgmath.h: New.

gcc:
	* builtins.c (fold_builtin_sincos): Build COMPOUND_EXPR in
	void_type_node.
	(fold_call_expr): Return a NOP_EXPR from folding rather than the
	contained expression.
	* c-common.c (c_fully_fold, c_fully_fold_internal, c_save_expr):
	New.
	(c_common_truthvalue_conversion): Use c_save_expr.  Do not fold
	conditional expressions for C.
	(decl_constant_value_for_optimization): Move from
	decl_constant_value_for_broken_optimization in c-typeck.c.  Check
	whether optimizing and that the expression is a VAR_DECL not of
	array type instead of doing such checks in the caller.  Do not
	check pedantic.  Call gcc_unreachable for C++.
	* c-common.def (C_MAYBE_CONST_EXPR): New.
	* c-common.h (c_fully_fold, c_save_expr,
	decl_constant_value_for_optimization): New prototypes.
	(C_MAYBE_CONST_EXPR_PRE, C_MAYBE_CONST_EXPR_EXPR,
	C_MAYBE_CONST_EXPR_INT_OPERANDS, C_MAYBE_CONST_EXPR_NON_CONST,
	EXPR_INT_CONST_OPERANDS): Define.
	* c-convert.c (convert): Strip nops from expression.
	* c-decl.c (groktypename): Take extra parameters expr and
	expr_const_operands.  Update call to grokdeclarator.
	(start_decl): Update call to grokdeclarator.  Add statement for
	expressions used in type of decl.
	(grokparm): Update call to grokdeclarator.
	(push_parm_decl): Update call to grokdeclarator.
	(build_compound_literal): Add parameter non_const and build a
	C_MAYBE_COSNT_EXPR if applicable.
	(grokdeclarator): Take extra parameters expr and
	expr_const_operands.  Track expressions used in declaration
	specifiers and declarators.  Fold array sizes and track whether
	they are constant expressions and whether they are integer
	constant expressions.
	(parser_xref_tag): Set expr and expr_const_operands fields in
	return value.
	(grokfield): Update call to grokdeclarator.
	(start_function): Update call to grokdeclarator.
	(build_null_declspecs): Set expr and expr_const_operands fields in
	return value.
	(declspecs_add_type): Handle expressions in typeof specifiers.
	* c-parser.c (c_parser_declspecs): Set expr and
	expr_const_operands fields for declaration specifiers.
	(c_parser_enum_specifier): Likewise.
	(c_parser_struct_or_union_specifier): Likewise.
	(c_parser_typeof_specifier): Likewise.  Update call to
	groktypename.  Fold expression as needed.  Return expressions with
	type instead of adding statements.
	(c_parser_attributes): Update calls to c_parser_expr_list.
	(c_parser_statement_after_labels): Fold expression before passing
	to objc_build_throw_stmt.
	(c_parser_condition): Fold expression.
	(c_parser_asm_operands): Fold expression.
	(c_parser_conditional_expression): Use c_save_expr.  Update call
	to build_conditional_expr.
	(c_parser_alignof_expression): Update call to groktypename.
	(c_parser_postfix_expression): Preserve C_MAYBE_CONST_EXPR as
	original_code.  Fold expression argument of va_arg.  Create
	C_MAYBE_CONST_EXPR to preserve side effects of expressions in type
	argument to va_arg.  Update calls to groktypename.  Fold array
	index for offsetof.  Verify that first argument to
	__builtin_choose_expr has integer type.
	(c_parser_postfix_expression_after_paren_type): Update calls to
	groktypename and build_compound_literal.  Handle expressions with
	side effects in type name.
	(c_parser_postfix_expression_after_primary): Update call to
	c_parser_expr_list.  Set original_code for calls to
	__builtin_constant_p.
	(c_parser_expr_list): Take extra parameter fold_p.  Fold
	expressions if requested.
	(c_parser_objc_type_name): Update call to groktypename.
	(c_parser_objc_synchronized_statement): Fold expression.
	(c_parser_objc_receiver): Fold expression.
	(c_parser_objc_keywordexpr): Update call to c_parser_expr_list.
	(c_parser_omp_clause_num_threads, c_parser_omp_clause_schedule,
	c_parser_omp_atomic, c_parser_omp_for_loop): Fold expressions.
	* c-tree.h (CONSTRUCTOR_NON_CONST): Define.
	(struct c_typespec): Add elements expr and expr_const_operands.
	(struct c_declspecs): Add elements expr and expr_const_operands.
	(groktypename, build_conditional_expr, build_compound_literal):
	Update prototypes.
	(in_late_binary_op): Declare.
	* c-typeck.c (note_integer_operands): New function.
	(in_late_binary_op): New variable.
	(decl_constant_value_for_broken_optimization): Move to c-common.c
	and rename to decl_constant_value_for_optimization.
	(default_function_array_conversion): Do not strip nops.
	(default_conversion): Do not call
	decl_constant_value_for_broken_optimization.
	(build_array_ref): Do not fold result.
	(c_expr_sizeof_expr): Fold operand.  Use C_MAYBE_CONST_EXPR for
	result when operand is a VLA.
	(c_expr_sizeof_type): Update call to groktypename.  Handle
	expressions included in type name.  Use C_MAYBE_CONST_EXPR for
	result when operand names a VLA type.
	(build_function_call): Update call to build_compound_literal.
	Only fold result for calls to __builtin_* functions.  Strip
	NOP_EXPR from INTEGER_CST returned from such functions.  Fold
	the function designator.
	(convert_arguments): Fold arguments.  Update call to
	convert_for_assignment.
	(build_unary_op): Handle increment and decrement of
	C_MAYBE_CONST_EXPR.  Move lvalue checks for increment and
	decrement earlier.  Fold operand of increment and decrement.
	Handle address of C_MAYBE_CONST_EXPR.  Only fold expression being
	built for integer operand.  Wrap returns that are INTEGER_CSTs
	without being integer constant expressions or that have integer
	constant operands without being INTEGER_CSTs.
	(lvalue_p): Handle C_MAYBE_CONST_EXPR.
	(build_conditional_expr): Add operand ifexp_bcp.  Track whether
	result is an integer constant expression or can be used in
	unevaluated parts of one and avoid folding and wrap as
	appropriate.  Fold operands before possibly doing -Wsign-compare
	warnings.
	(build_compound_expr): Wrap result for C99 if operands can be used
	in integer constant expressions.
	(build_c_cast): Update call to digest_init.  Do not ignore
	overflow from casting floating-point constants to integers.  Wrap
	results that could be confused with integer constant expressions,
	null pointer constants or floating-point constants.
	(c_cast_expr): Update call to groktypename.  Handle expressions
	included in type name.
	(build_modify_expr): Handle modifying a C_MAYBE_CONST_EXPR.  Fold
	lhs inside possible SAVE_EXPR.  Fold RHS before assignment.
	Update calls to convert_for_assignment.
	(convert_for_assignment): Take new parameter
	null_pointer_constant.  Do not strip nops or call
	decl_constant_value_for_broken_optimization.  Set
	in_late_binary_op for conversions to boolean.
	(store_init_value): Update call to digest_init.
	(digest_init): Take new parameter null_pointer_constant.  Do not
	call decl_constant_value_for_broken_optimization.  pedwarn for
	initializers not constant expressions.  Update calls to
	convert_for_assignment.
	(constructor_nonconst): New.
	(struct constructor_stack): Add nonconst element.
	(really_start_incremental_init, push_init_level, pop_init_level):
	Handle constructor_nonconst and nonconst element.
	(set_init_index): Call constant_expression_warning for array
	designators.
	(output_init_element): Fold value.  Set constructor_nonconst as
	applicable.  pedwarn for initializers not constant expressions.
	Update call to digest_init.  Call constant_expression_warning
	where constant initializers are required.
	(process_init_element): Use c_save_expr.
	(c_finish_goto_ptr): Fold expression.
	(c_finish_return): Fold return value.  Update call to
	convert_for_assignment.
	(c_start_case): Fold switch expression.
	(c_process_expr_stmt): Fold expression.
	(c_finish_stmt_expr): Create C_MAYBE_CONST_EXPR as needed to
	ensure statement expression is not evaluated in constant
	expression.
	(build_binary_op): Track whether results are integer constant
	expressions or may occur in such, disable folding and wrap results
	as applicable.  Fold operands for -Wsign-compare warnings unless
	in_late_binary_op.
	(c_objc_common_truthvalue_conversion): Handle results folded to
	integer constants that are not integer constant expressions.
	* doc/extend.texi: Document when typeof operands are evaluated,
	that condition of __builtin_choose_expr is an integer constant
	expression, and more about use of __builtin_constant_p in
	initializers.

gcc/objc:
	* objc-act.c (objc_finish_try_stmt): Set in_late_binary_op.

gcc/testsuite:
	* gcc.c-torture/compile/20081108-1.c,
	gcc.c-torture/compile/20081108-2.c,
	gcc.c-torture/compile/20081108-3.c, gcc.dg/bconstp-2.c,
	gcc.dg/bconstp-3.c, gcc.dg/bconstp-4.c, gcc.dg/c90-const-expr-6.c,
	gcc.dg/c90-const-expr-7.c, gcc.dg/c90-const-expr-8.c,
	gcc.dg/c90-const-expr-9.c, gcc.dg/c90-const-expr-10.c,
	gcc.dg/c90-const-expr-11.c, gcc.dg/c99-const-expr-6.c,
	gcc.dg/c99-const-expr-7.c, gcc.dg/c99-const-expr-8.c,
	gcc.dg/c99-const-expr-9.c, gcc.dg/c99-const-expr-10.c,
	gcc.dg/c99-const-expr-11.c, gcc.dg/c99-const-expr-12.c,
	gcc.dg/c99-const-expr-13.c, gcc.dg/compare10.c,
	gcc.dg/gnu89-const-expr-1.c, gcc.dg/gnu89-const-expr-2.c,
	gcc.dg/gnu99-const-expr-1.c, gcc.dg/gnu99-const-expr-2.c,
	gcc.dg/gnu99-const-expr-3.c, gcc.dg/vla-12.c, gcc.dg/vla-13.c,
	gcc.dg/vla-14.c, gcc.dg/vla-15.c, gcc.dg/vla-16.c: New tests.
	* gcc.dg/c90-const-expr-1.c, gcc.dg/c90-const-expr-2.c,
	gcc.dg/c90-const-expr-3.c, gcc.dg/c99-const-expr-2.c,
	gcc.dg/c99-const-expr-3.c, gcc.dg/c99-static-1.c: Remove XFAILs.
	* gcc.dg/c90-const-expr-2.c: Use ZERO in place of 0 in another
	case.
	* gcc.dg/overflow-warn-1.c, gcc.dg/overflow-warn-2.c,
	gcc.dg/overflow-warn-3.c, gcc.dg/overflow-warn-4.c: Remove
	XFAILs.  Update expected messages.
	* gcc.dg/pr14649-1.c, gcc.dg/pr19984.c, gcc.dg/pr25682.c: Update
	expected messages.
	* gcc.dg/real-const-1.c: Replace with test from original PR.
	* gcc.dg/vect/pr32230.c: Use intermediate cast to __PTRDIFF_TYPE__
	when casting from non-constant integer to pointer.

From-SVN: r145254
parent 5babbcc0
2009-03-29 Joseph Myers <joseph@codesourcery.com>
PR c/456
PR c/5675
PR c/19976
PR c/29116
PR c/31871
PR c/35198
* inclhack.def (glibc_tgmath): New fix.
* fixincl.x: Regenerate.
* tests/base/tgmath.h: New.
2009-03-28 Joseph Myers <joseph@codesourcery.com> 2009-03-28 Joseph Myers <joseph@codesourcery.com>
* inclhack.def (aix_syswait, exception_structure, * inclhack.def (aix_syswait, exception_structure,
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
* *
* DO NOT EDIT THIS FILE (fixincl.x) * DO NOT EDIT THIS FILE (fixincl.x)
* *
* It has been AutoGen-ed Saturday March 28, 2009 at 12:12:55 AM UTC * It has been AutoGen-ed Sunday March 29, 2009 at 01:30:25 AM UTC
* From the definitions inclhack.def * From the definitions inclhack.def
* and the template file fixincl * and the template file fixincl
*/ */
/* DO NOT SVN-MERGE THIS FILE, EITHER Sat Mar 28 00:12:55 UTC 2009 /* DO NOT SVN-MERGE THIS FILE, EITHER Sun Mar 29 01:30:25 UTC 2009
* *
* You must regenerate it. Use the ./genfixes script. * You must regenerate it. Use the ./genfixes script.
* *
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* certain ANSI-incompatible system header files which are fixed to work * certain ANSI-incompatible system header files which are fixed to work
* correctly with ANSI C and placed in a directory that GNU C will search. * correctly with ANSI C and placed in a directory that GNU C will search.
* *
* This file contains 177 fixup descriptions. * This file contains 178 fixup descriptions.
* *
* See README for more information. * See README for more information.
* *
...@@ -2219,6 +2219,49 @@ s/{ { 0, } }/{ { 0, 0, 0, 0, 0, 0 } }/\n\ ...@@ -2219,6 +2219,49 @@ s/{ { 0, } }/{ { 0, 0, 0, 0, 0, 0 } }/\n\
/* * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Description of Glibc_Tgmath fix
*/
tSCC zGlibc_TgmathName[] =
"glibc_tgmath";
/*
* File name selection pattern
*/
tSCC zGlibc_TgmathList[] =
"tgmath.h\0";
/*
* Machine/OS name selection pattern
*/
#define apzGlibc_TgmathMachs (const char**)NULL
/*
* content selection pattern - do fix if pattern found
*/
tSCC zGlibc_TgmathSelect0[] =
"\\(\\(\\(type\\) 0.25\\) && \\(\\(type\\) 0.25 - 1\\)\\)";
/*
* content bypass pattern - skip fix if pattern found
*/
tSCC zGlibc_TgmathBypass0[] =
"__floating_type \\\\\n\
.*__builtin_classify_type";
#define GLIBC_TGMATH_TEST_CT 2
static tTestDesc aGlibc_TgmathTests[] = {
{ TT_NEGREP, zGlibc_TgmathBypass0, (regex_t*)NULL },
{ TT_EGREP, zGlibc_TgmathSelect0, (regex_t*)NULL }, };
/*
* Fix Command Arguments for Glibc_Tgmath
*/
static const char* apzGlibc_TgmathPatch[] = {
"format",
"(__builtin_classify_type ((type) 0) == 8 || (__builtin_classify_type ((type) 0) == 9 && __builtin_classify_type (__real__ ((type) 0)) == 8))",
(char*)NULL };
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Description of Gnu_Types fix * Description of Gnu_Types fix
*/ */
tSCC zGnu_TypesName[] = tSCC zGnu_TypesName[] =
...@@ -7192,9 +7235,9 @@ static const char* apzX11_SprintfPatch[] = { ...@@ -7192,9 +7235,9 @@ static const char* apzX11_SprintfPatch[] = {
* *
* List of all fixes * List of all fixes
*/ */
#define REGEX_COUNT 221 #define REGEX_COUNT 223
#define MACH_LIST_SIZE_LIMIT 181 #define MACH_LIST_SIZE_LIMIT 181
#define FIX_COUNT 177 #define FIX_COUNT 178
/* /*
* Enumerate the fixes * Enumerate the fixes
...@@ -7253,6 +7296,7 @@ typedef enum { ...@@ -7253,6 +7296,7 @@ typedef enum {
GLIBC_C99_INLINE_3_FIXIDX, GLIBC_C99_INLINE_3_FIXIDX,
GLIBC_C99_INLINE_4_FIXIDX, GLIBC_C99_INLINE_4_FIXIDX,
GLIBC_MUTEX_INIT_FIXIDX, GLIBC_MUTEX_INIT_FIXIDX,
GLIBC_TGMATH_FIXIDX,
GNU_TYPES_FIXIDX, GNU_TYPES_FIXIDX,
HP_INLINE_FIXIDX, HP_INLINE_FIXIDX,
HP_SYSFILE_FIXIDX, HP_SYSFILE_FIXIDX,
...@@ -7645,6 +7689,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = { ...@@ -7645,6 +7689,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY, GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY,
aGlibc_Mutex_InitTests, apzGlibc_Mutex_InitPatch, 0 }, aGlibc_Mutex_InitTests, apzGlibc_Mutex_InitPatch, 0 },
{ zGlibc_TgmathName, zGlibc_TgmathList,
apzGlibc_TgmathMachs,
GLIBC_TGMATH_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
aGlibc_TgmathTests, apzGlibc_TgmathPatch, 0 },
{ zGnu_TypesName, zGnu_TypesList, { zGnu_TypesName, zGnu_TypesList,
apzGnu_TypesMachs, apzGnu_TypesMachs,
GNU_TYPES_TEST_CT, FD_MACH_IFNOT | FD_SUBROUTINE, GNU_TYPES_TEST_CT, FD_MACH_IFNOT | FD_SUBROUTINE,
......
...@@ -1265,6 +1265,19 @@ fix = { ...@@ -1265,6 +1265,19 @@ fix = {
}; };
/* glibc's tgmath.h relies on an expression that is not an integer
constant expression being treated as it was by GCC 4.4 and
earlier. */
fix = {
hackname = glibc_tgmath;
files = tgmath.h;
select = '\(\(\(type\) 0.25\) && \(\(type\) 0.25 - 1\)\)';
bypass = "__floating_type \\\\\n.*__builtin_classify_type";
c_fix = format;
c_fix_arg = "(__builtin_classify_type ((type) 0) == 8 || (__builtin_classify_type ((type) 0) == 9 && __builtin_classify_type (__real__ ((type) 0)) == 8))";
test_text = "# define __floating_type(type) (((type) 0.25) && ((type) 0.25 - 1))";
};
/* /*
* Fix these files to use the types we think they should for * Fix these files to use the types we think they should for
* ptrdiff_t, size_t, and wchar_t. * ptrdiff_t, size_t, and wchar_t.
......
/* DO NOT EDIT THIS FILE.
It has been auto-edited by fixincludes from:
"fixinc/tests/inc/tgmath.h"
This had to be done to correct non-standard usages in the
original, manufacturer supplied header file. */
#if defined( GLIBC_TGMATH_CHECK )
# define __floating_type(type) (__builtin_classify_type ((type) 0) == 8 || (__builtin_classify_type ((type) 0) == 9 && __builtin_classify_type (__real__ ((type) 0)) == 8))
#endif /* GLIBC_TGMATH_CHECK */
2009-03-29 Joseph Myers <joseph@codesourcery.com>
PR c/456
PR c/5675
PR c/19976
PR c/29116
PR c/31871
PR c/35198
* builtins.c (fold_builtin_sincos): Build COMPOUND_EXPR in
void_type_node.
(fold_call_expr): Return a NOP_EXPR from folding rather than the
contained expression.
* c-common.c (c_fully_fold, c_fully_fold_internal, c_save_expr):
New.
(c_common_truthvalue_conversion): Use c_save_expr. Do not fold
conditional expressions for C.
(decl_constant_value_for_optimization): Move from
decl_constant_value_for_broken_optimization in c-typeck.c. Check
whether optimizing and that the expression is a VAR_DECL not of
array type instead of doing such checks in the caller. Do not
check pedantic. Call gcc_unreachable for C++.
* c-common.def (C_MAYBE_CONST_EXPR): New.
* c-common.h (c_fully_fold, c_save_expr,
decl_constant_value_for_optimization): New prototypes.
(C_MAYBE_CONST_EXPR_PRE, C_MAYBE_CONST_EXPR_EXPR,
C_MAYBE_CONST_EXPR_INT_OPERANDS, C_MAYBE_CONST_EXPR_NON_CONST,
EXPR_INT_CONST_OPERANDS): Define.
* c-convert.c (convert): Strip nops from expression.
* c-decl.c (groktypename): Take extra parameters expr and
expr_const_operands. Update call to grokdeclarator.
(start_decl): Update call to grokdeclarator. Add statement for
expressions used in type of decl.
(grokparm): Update call to grokdeclarator.
(push_parm_decl): Update call to grokdeclarator.
(build_compound_literal): Add parameter non_const and build a
C_MAYBE_COSNT_EXPR if applicable.
(grokdeclarator): Take extra parameters expr and
expr_const_operands. Track expressions used in declaration
specifiers and declarators. Fold array sizes and track whether
they are constant expressions and whether they are integer
constant expressions.
(parser_xref_tag): Set expr and expr_const_operands fields in
return value.
(grokfield): Update call to grokdeclarator.
(start_function): Update call to grokdeclarator.
(build_null_declspecs): Set expr and expr_const_operands fields in
return value.
(declspecs_add_type): Handle expressions in typeof specifiers.
* c-parser.c (c_parser_declspecs): Set expr and
expr_const_operands fields for declaration specifiers.
(c_parser_enum_specifier): Likewise.
(c_parser_struct_or_union_specifier): Likewise.
(c_parser_typeof_specifier): Likewise. Update call to
groktypename. Fold expression as needed. Return expressions with
type instead of adding statements.
(c_parser_attributes): Update calls to c_parser_expr_list.
(c_parser_statement_after_labels): Fold expression before passing
to objc_build_throw_stmt.
(c_parser_condition): Fold expression.
(c_parser_asm_operands): Fold expression.
(c_parser_conditional_expression): Use c_save_expr. Update call
to build_conditional_expr.
(c_parser_alignof_expression): Update call to groktypename.
(c_parser_postfix_expression): Preserve C_MAYBE_CONST_EXPR as
original_code. Fold expression argument of va_arg. Create
C_MAYBE_CONST_EXPR to preserve side effects of expressions in type
argument to va_arg. Update calls to groktypename. Fold array
index for offsetof. Verify that first argument to
__builtin_choose_expr has integer type.
(c_parser_postfix_expression_after_paren_type): Update calls to
groktypename and build_compound_literal. Handle expressions with
side effects in type name.
(c_parser_postfix_expression_after_primary): Update call to
c_parser_expr_list. Set original_code for calls to
__builtin_constant_p.
(c_parser_expr_list): Take extra parameter fold_p. Fold
expressions if requested.
(c_parser_objc_type_name): Update call to groktypename.
(c_parser_objc_synchronized_statement): Fold expression.
(c_parser_objc_receiver): Fold expression.
(c_parser_objc_keywordexpr): Update call to c_parser_expr_list.
(c_parser_omp_clause_num_threads, c_parser_omp_clause_schedule,
c_parser_omp_atomic, c_parser_omp_for_loop): Fold expressions.
* c-tree.h (CONSTRUCTOR_NON_CONST): Define.
(struct c_typespec): Add elements expr and expr_const_operands.
(struct c_declspecs): Add elements expr and expr_const_operands.
(groktypename, build_conditional_expr, build_compound_literal):
Update prototypes.
(in_late_binary_op): Declare.
* c-typeck.c (note_integer_operands): New function.
(in_late_binary_op): New variable.
(decl_constant_value_for_broken_optimization): Move to c-common.c
and rename to decl_constant_value_for_optimization.
(default_function_array_conversion): Do not strip nops.
(default_conversion): Do not call
decl_constant_value_for_broken_optimization.
(build_array_ref): Do not fold result.
(c_expr_sizeof_expr): Fold operand. Use C_MAYBE_CONST_EXPR for
result when operand is a VLA.
(c_expr_sizeof_type): Update call to groktypename. Handle
expressions included in type name. Use C_MAYBE_CONST_EXPR for
result when operand names a VLA type.
(build_function_call): Update call to build_compound_literal.
Only fold result for calls to __builtin_* functions. Strip
NOP_EXPR from INTEGER_CST returned from such functions. Fold
the function designator.
(convert_arguments): Fold arguments. Update call to
convert_for_assignment.
(build_unary_op): Handle increment and decrement of
C_MAYBE_CONST_EXPR. Move lvalue checks for increment and
decrement earlier. Fold operand of increment and decrement.
Handle address of C_MAYBE_CONST_EXPR. Only fold expression being
built for integer operand. Wrap returns that are INTEGER_CSTs
without being integer constant expressions or that have integer
constant operands without being INTEGER_CSTs.
(lvalue_p): Handle C_MAYBE_CONST_EXPR.
(build_conditional_expr): Add operand ifexp_bcp. Track whether
result is an integer constant expression or can be used in
unevaluated parts of one and avoid folding and wrap as
appropriate. Fold operands before possibly doing -Wsign-compare
warnings.
(build_compound_expr): Wrap result for C99 if operands can be used
in integer constant expressions.
(build_c_cast): Update call to digest_init. Do not ignore
overflow from casting floating-point constants to integers. Wrap
results that could be confused with integer constant expressions,
null pointer constants or floating-point constants.
(c_cast_expr): Update call to groktypename. Handle expressions
included in type name.
(build_modify_expr): Handle modifying a C_MAYBE_CONST_EXPR. Fold
lhs inside possible SAVE_EXPR. Fold RHS before assignment.
Update calls to convert_for_assignment.
(convert_for_assignment): Take new parameter
null_pointer_constant. Do not strip nops or call
decl_constant_value_for_broken_optimization. Set
in_late_binary_op for conversions to boolean.
(store_init_value): Update call to digest_init.
(digest_init): Take new parameter null_pointer_constant. Do not
call decl_constant_value_for_broken_optimization. pedwarn for
initializers not constant expressions. Update calls to
convert_for_assignment.
(constructor_nonconst): New.
(struct constructor_stack): Add nonconst element.
(really_start_incremental_init, push_init_level, pop_init_level):
Handle constructor_nonconst and nonconst element.
(set_init_index): Call constant_expression_warning for array
designators.
(output_init_element): Fold value. Set constructor_nonconst as
applicable. pedwarn for initializers not constant expressions.
Update call to digest_init. Call constant_expression_warning
where constant initializers are required.
(process_init_element): Use c_save_expr.
(c_finish_goto_ptr): Fold expression.
(c_finish_return): Fold return value. Update call to
convert_for_assignment.
(c_start_case): Fold switch expression.
(c_process_expr_stmt): Fold expression.
(c_finish_stmt_expr): Create C_MAYBE_CONST_EXPR as needed to
ensure statement expression is not evaluated in constant
expression.
(build_binary_op): Track whether results are integer constant
expressions or may occur in such, disable folding and wrap results
as applicable. Fold operands for -Wsign-compare warnings unless
in_late_binary_op.
(c_objc_common_truthvalue_conversion): Handle results folded to
integer constants that are not integer constant expressions.
* doc/extend.texi: Document when typeof operands are evaluated,
that condition of __builtin_choose_expr is an integer constant
expression, and more about use of __builtin_constant_p in
initializers.
2009-03-29 Richard Guenther <rguenther@suse.de> 2009-03-29 Richard Guenther <rguenther@suse.de>
* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Properly * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Properly
......
...@@ -7930,7 +7930,7 @@ fold_builtin_sincos (tree arg0, tree arg1, tree arg2) ...@@ -7930,7 +7930,7 @@ fold_builtin_sincos (tree arg0, tree arg1, tree arg2)
call = build_call_expr (fn, 1, arg0); call = build_call_expr (fn, 1, arg0);
call = builtin_save_expr (call); call = builtin_save_expr (call);
return build2 (COMPOUND_EXPR, type, return build2 (COMPOUND_EXPR, void_type_node,
build2 (MODIFY_EXPR, void_type_node, build2 (MODIFY_EXPR, void_type_node,
build_fold_indirect_ref (arg1), build_fold_indirect_ref (arg1),
build1 (IMAGPART_EXPR, type, call)), build1 (IMAGPART_EXPR, type, call)),
...@@ -10929,7 +10929,6 @@ fold_call_expr (tree exp, bool ignore) ...@@ -10929,7 +10929,6 @@ fold_call_expr (tree exp, bool ignore)
if (CAN_HAVE_LOCATION_P (realret) if (CAN_HAVE_LOCATION_P (realret)
&& !EXPR_HAS_LOCATION (realret)) && !EXPR_HAS_LOCATION (realret))
SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp)); SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
return realret;
} }
return ret; return ret;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
additional tree codes used in the GNU C compiler (see tree.def additional tree codes used in the GNU C compiler (see tree.def
for the standard codes). for the standard codes).
Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998,
1999, 2000, 2001, 2004, 2005, 2007 Free Software Foundation, Inc. 1999, 2000, 2001, 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
Written by Benjamin Chelf <chelf@codesourcery.com> Written by Benjamin Chelf <chelf@codesourcery.com>
This file is part of GCC. This file is part of GCC.
...@@ -31,6 +31,21 @@ along with GCC; see the file COPYING3. If not see ...@@ -31,6 +31,21 @@ along with GCC; see the file COPYING3. If not see
the compound literal. */ the compound literal. */
DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", tcc_expression, 1) DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", tcc_expression, 1)
/* A C_MAYBE_CONST_EXPR, currently only used for C and Objective C,
tracks information about constancy of an expression and VLA type
sizes or VM expressions from typeof that need to be evaluated
before the main expression. It is used during parsing and removed
in c_fully_fold. C_MAYBE_CONST_EXPR_PRE is the expression to
evaluate first, if not NULL; C_MAYBE_CONST_EXPR_EXPR is the main
expression. If C_MAYBE_CONST_EXPR_INT_OPERANDS is set then the
expression may be used in an unevaluated part of an integer
constant expression, but not in an evaluated part. If
C_MAYBE_CONST_EXPR_NON_CONST is set then the expression contains
something that cannot occur in an evaluated part of a constant
expression (or outside of sizeof in C90 mode); otherwise it does
not. */
DEFTREECODE (C_MAYBE_CONST_EXPR, "c_maybe_const_expr", tcc_expression, 2)
/* /*
Local variables: Local variables:
mode:c mode:c
......
/* Definitions for c-common.c. /* Definitions for c-common.c.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998, Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -30,8 +30,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -30,8 +30,10 @@ along with GCC; see the file COPYING3. If not see
0: TREE_NEGATED_INT (in INTEGER_CST). 0: TREE_NEGATED_INT (in INTEGER_CST).
IDENTIFIER_MARKED (used by search routines). IDENTIFIER_MARKED (used by search routines).
DECL_PRETTY_FUNCTION_P (in VAR_DECL) DECL_PRETTY_FUNCTION_P (in VAR_DECL)
C_MAYBE_CONST_EXPR_INT_OPERANDS (in C_MAYBE_CONST_EXPR, for C)
1: C_DECLARED_LABEL_FLAG (in LABEL_DECL) 1: C_DECLARED_LABEL_FLAG (in LABEL_DECL)
STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST) STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST)
C_MAYBE_CONST_EXPR_NON_CONST (in C_MAYBE_CONST_EXPR, for C)
2: unused 2: unused
3: STATEMENT_LIST_HAS_LABEL (in STATEMENT_LIST) 3: STATEMENT_LIST_HAS_LABEL (in STATEMENT_LIST)
4: unused 4: unused
...@@ -715,6 +717,9 @@ extern tree c_common_signed_type (tree); ...@@ -715,6 +717,9 @@ extern tree c_common_signed_type (tree);
extern tree c_common_signed_or_unsigned_type (int, tree); extern tree c_common_signed_or_unsigned_type (int, tree);
extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int); extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
extern bool decl_with_nonnull_addr_p (const_tree); extern bool decl_with_nonnull_addr_p (const_tree);
extern tree c_fully_fold (tree, bool, bool *);
extern tree decl_constant_value_for_optimization (tree);
extern tree c_save_expr (tree);
extern tree c_common_truthvalue_conversion (location_t, tree); extern tree c_common_truthvalue_conversion (location_t, tree);
extern void c_apply_type_quals_to_decl (int, tree); extern void c_apply_type_quals_to_decl (int, tree);
extern tree c_sizeof_or_alignof_type (tree, bool, int); extern tree c_sizeof_or_alignof_type (tree, bool, int);
...@@ -799,6 +804,21 @@ extern void finish_file (void); ...@@ -799,6 +804,21 @@ extern void finish_file (void);
#define COMPOUND_LITERAL_EXPR_DECL(NODE) \ #define COMPOUND_LITERAL_EXPR_DECL(NODE) \
DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE)) DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE))
/* C_MAYBE_CONST_EXPR accessors. */
#define C_MAYBE_CONST_EXPR_PRE(NODE) \
TREE_OPERAND (C_MAYBE_CONST_EXPR_CHECK (NODE), 0)
#define C_MAYBE_CONST_EXPR_EXPR(NODE) \
TREE_OPERAND (C_MAYBE_CONST_EXPR_CHECK (NODE), 1)
#define C_MAYBE_CONST_EXPR_INT_OPERANDS(NODE) \
TREE_LANG_FLAG_0 (C_MAYBE_CONST_EXPR_CHECK (NODE))
#define C_MAYBE_CONST_EXPR_NON_CONST(NODE) \
TREE_LANG_FLAG_1 (C_MAYBE_CONST_EXPR_CHECK (NODE))
#define EXPR_INT_CONST_OPERANDS(EXPR) \
(INTEGRAL_TYPE_P (TREE_TYPE (EXPR)) \
&& (TREE_CODE (EXPR) == INTEGER_CST \
|| (TREE_CODE (EXPR) == C_MAYBE_CONST_EXPR \
&& C_MAYBE_CONST_EXPR_INT_OPERANDS (EXPR))))
/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */ /* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
#define DECL_C_BIT_FIELD(NODE) \ #define DECL_C_BIT_FIELD(NODE) \
(DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1) (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
......
/* Language-level data type conversion for GNU C. /* Language-level data type conversion for GNU C.
Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008 Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008,
Free Software Foundation, Inc. 2009 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -86,6 +86,8 @@ convert (tree type, tree expr) ...@@ -86,6 +86,8 @@ convert (tree type, tree expr)
if (type == TREE_TYPE (expr)) if (type == TREE_TYPE (expr))
return expr; return expr;
STRIP_TYPE_NOPS (e);
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
return fold_convert (type, expr); return fold_convert (type, expr);
if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
......
...@@ -146,6 +146,10 @@ struct lang_type GTY(()) ...@@ -146,6 +146,10 @@ struct lang_type GTY(())
without prototypes. */ without prototypes. */
#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE) #define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE)
/* For a CONSTRUCTOR, whether some initializer contains a
subexpression meaning it is not a constant expression. */
#define CONSTRUCTOR_NON_CONST(EXPR) TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (EXPR))
/* Record parser information about an expression that is irrelevant /* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */ for code generation alongside a tree representing its value. */
struct c_expr struct c_expr
...@@ -154,7 +158,9 @@ struct c_expr ...@@ -154,7 +158,9 @@ struct c_expr
tree value; tree value;
/* Record the original unary/binary operator of an expression, which may /* Record the original unary/binary operator of an expression, which may
have been changed by fold, STRING_CST for unparenthesized string have been changed by fold, STRING_CST for unparenthesized string
constants, or ERROR_MARK for other expressions (including constants, C_MAYBE_CONST_EXPR for __builtin_constant_p calls
(even if parenthesized), for subexpressions, and for non-constant
initializers, or ERROR_MARK for other expressions (including
parenthesized expressions). */ parenthesized expressions). */
enum tree_code original_code; enum tree_code original_code;
}; };
...@@ -190,6 +196,18 @@ struct c_typespec { ...@@ -190,6 +196,18 @@ struct c_typespec {
enum c_typespec_kind kind; enum c_typespec_kind kind;
/* The specifier itself. */ /* The specifier itself. */
tree spec; tree spec;
/* An expression to be evaluated before the type specifier, in the
case of typeof specifiers, or NULL otherwise or if no such
expression is required for a particular typeof specifier. In
particular, when typeof is applied to an expression of variably
modified type, that expression must be evaluated in order to
determine array sizes that form part of the type, but the
expression itself (as opposed to the array sizes) forms no part
of the type and so needs to be recorded separately. */
tree expr;
/* Whether the expression has operands suitable for use in constant
expressions. */
bool expr_const_operands;
}; };
/* A storage class specifier. */ /* A storage class specifier. */
...@@ -227,6 +245,9 @@ struct c_declspecs { ...@@ -227,6 +245,9 @@ struct c_declspecs {
whole type, or NULL_TREE if none or a keyword such as "void" or whole type, or NULL_TREE if none or a keyword such as "void" or
"char" is used. Does not include qualifiers. */ "char" is used. Does not include qualifiers. */
tree type; tree type;
/* Any expression to be evaluated before the type, from a typeof
specifier. */
tree expr;
/* The attributes from a typedef decl. */ /* The attributes from a typedef decl. */
tree decl_attr; tree decl_attr;
/* When parsing, the attributes. Outside the parser, this will be /* When parsing, the attributes. Outside the parser, this will be
...@@ -238,6 +259,9 @@ struct c_declspecs { ...@@ -238,6 +259,9 @@ struct c_declspecs {
enum c_typespec_keyword typespec_word; enum c_typespec_keyword typespec_word;
/* The storage class specifier, or csc_none if none. */ /* The storage class specifier, or csc_none if none. */
enum c_storage_class storage_class; enum c_storage_class storage_class;
/* Whether any expressions in typeof specifiers may appear in
constant expressions. */
BOOL_BITFIELD expr_const_operands : 1;
/* Whether any declaration specifiers have been seen at all. */ /* Whether any declaration specifiers have been seen at all. */
BOOL_BITFIELD declspecs_seen_p : 1; BOOL_BITFIELD declspecs_seen_p : 1;
/* Whether a type specifier has been seen. */ /* Whether a type specifier has been seen. */
...@@ -478,7 +502,7 @@ extern tree finish_struct (tree, tree, tree); ...@@ -478,7 +502,7 @@ extern tree finish_struct (tree, tree, tree);
extern struct c_arg_info *get_parm_info (bool); extern struct c_arg_info *get_parm_info (bool);
extern tree grokfield (location_t, struct c_declarator *, extern tree grokfield (location_t, struct c_declarator *,
struct c_declspecs *, tree, tree *); struct c_declspecs *, tree, tree *);
extern tree groktypename (struct c_type_name *); extern tree groktypename (struct c_type_name *, tree *, bool *);
extern tree grokparm (const struct c_parm *); extern tree grokparm (const struct c_parm *);
extern tree implicitly_declare (tree); extern tree implicitly_declare (tree);
extern void keep_next_level (void); extern void keep_next_level (void);
...@@ -532,6 +556,7 @@ extern bool c_vla_unspec_p (tree x, tree fn); ...@@ -532,6 +556,7 @@ extern bool c_vla_unspec_p (tree x, tree fn);
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0)) ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
/* in c-typeck.c */ /* in c-typeck.c */
extern bool in_late_binary_op;
extern int in_alignof; extern int in_alignof;
extern int in_sizeof; extern int in_sizeof;
extern int in_typeof; extern int in_typeof;
...@@ -561,7 +586,7 @@ extern struct c_expr parser_build_unary_op (enum tree_code, struct c_expr, ...@@ -561,7 +586,7 @@ extern struct c_expr parser_build_unary_op (enum tree_code, struct c_expr,
extern struct c_expr parser_build_binary_op (location_t, extern struct c_expr parser_build_binary_op (location_t,
enum tree_code, struct c_expr, enum tree_code, struct c_expr,
struct c_expr); struct c_expr);
extern tree build_conditional_expr (tree, tree, tree); extern tree build_conditional_expr (tree, bool, tree, tree);
extern tree build_compound_expr (tree, tree); extern tree build_compound_expr (tree, tree);
extern tree c_cast_expr (struct c_type_name *, tree); extern tree c_cast_expr (struct c_type_name *, tree);
extern tree build_c_cast (tree, tree); extern tree build_c_cast (tree, tree);
...@@ -577,7 +602,7 @@ extern struct c_expr pop_init_level (int); ...@@ -577,7 +602,7 @@ extern struct c_expr pop_init_level (int);
extern void set_init_index (tree, tree); extern void set_init_index (tree, tree);
extern void set_init_label (tree); extern void set_init_label (tree);
extern void process_init_element (struct c_expr, bool); extern void process_init_element (struct c_expr, bool);
extern tree build_compound_literal (tree, tree); extern tree build_compound_literal (tree, tree, bool);
extern tree c_start_case (tree); extern tree c_start_case (tree);
extern void c_finish_case (tree); extern void c_finish_case (tree);
extern tree build_asm_expr (tree, tree, tree, tree, bool); extern tree build_asm_expr (tree, tree, tree, tree, bool);
......
...@@ -663,6 +663,10 @@ A @code{typeof}-construct can be used anywhere a typedef name could be ...@@ -663,6 +663,10 @@ A @code{typeof}-construct can be used anywhere a typedef name could be
used. For example, you can use it in a declaration, in a cast, or inside used. For example, you can use it in a declaration, in a cast, or inside
of @code{sizeof} or @code{typeof}. of @code{sizeof} or @code{typeof}.
The operand of @code{typeof} is evaluated for its side effects if and
only if it is an expression of variably modified type or the name of
such a type.
@code{typeof} is often useful in conjunction with the @code{typeof} is often useful in conjunction with the
statements-within-expressions feature. Here is how the two together can statements-within-expressions feature. Here is how the two together can
be used to define a safe ``maximum'' macro that operates on any be used to define a safe ``maximum'' macro that operates on any
...@@ -6635,9 +6639,8 @@ depending on the arguments' types. For example: ...@@ -6635,9 +6639,8 @@ depending on the arguments' types. For example:
You can use the built-in function @code{__builtin_choose_expr} to You can use the built-in function @code{__builtin_choose_expr} to
evaluate code depending on the value of a constant expression. This evaluate code depending on the value of a constant expression. This
built-in function returns @var{exp1} if @var{const_exp}, which is a built-in function returns @var{exp1} if @var{const_exp}, which is an
constant expression that must be able to be determined at compile time, integer constant expression, is nonzero. Otherwise it returns 0.
is nonzero. Otherwise it returns 0.
This built-in function is analogous to the @samp{? :} operator in C, This built-in function is analogous to the @samp{? :} operator in C,
except that the expression returned has its type unaltered by promotion except that the expression returned has its type unaltered by promotion
...@@ -6716,7 +6719,11 @@ static const int table[] = @{ ...@@ -6716,7 +6719,11 @@ static const int table[] = @{
@noindent @noindent
This is an acceptable initializer even if @var{EXPRESSION} is not a This is an acceptable initializer even if @var{EXPRESSION} is not a
constant expression. GCC must be more conservative about evaluating the constant expression, including the case where
@code{__builtin_constant_p} returns 1 because @var{EXPRESSION} can be
folded to a constant but @var{EXPRESSION} contains operands that would
not otherwize be permitted in a static initializer (for example,
@code{0 && foo ()}). GCC must be more conservative about evaluating the
built-in in this case, because it has no opportunity to perform built-in in this case, because it has no opportunity to perform
optimization. optimization.
......
2009-03-29 Joseph Myers <joseph@codesourcery.com>
PR c/456
PR c/5675
PR c/19976
PR c/29116
PR c/31871
PR c/35198
* objc-act.c (objc_finish_try_stmt): Set in_late_binary_op.
2008-12-05 Sebastian Pop <sebastian.pop@amd.com> 2008-12-05 Sebastian Pop <sebastian.pop@amd.com>
PR bootstrap/38262 PR bootstrap/38262
......
/* Implement classes and message passing for Objective C. /* Implement classes and message passing for Objective C.
Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Steve Naroff. Contributed by Steve Naroff.
This file is part of GCC. This file is part of GCC.
...@@ -3885,12 +3885,15 @@ objc_finish_try_stmt (void) ...@@ -3885,12 +3885,15 @@ objc_finish_try_stmt (void)
/* If we're doing Darwin setjmp exceptions, build the big nasty. */ /* If we're doing Darwin setjmp exceptions, build the big nasty. */
if (flag_objc_sjlj_exceptions) if (flag_objc_sjlj_exceptions)
{ {
bool save = in_late_binary_op;
in_late_binary_op = true;
if (!cur_try_context->finally_body) if (!cur_try_context->finally_body)
{ {
cur_try_context->finally_locus = input_location; cur_try_context->finally_locus = input_location;
cur_try_context->end_finally_locus = input_location; cur_try_context->end_finally_locus = input_location;
} }
stmt = next_sjlj_build_try_catch_finally (); stmt = next_sjlj_build_try_catch_finally ();
in_late_binary_op = save;
} }
else else
{ {
......
2009-03-29 Joseph Myers <joseph@codesourcery.com>
PR c/456
PR c/5675
PR c/19976
PR c/29116
PR c/31871
PR c/35198
* gcc.c-torture/compile/20081108-1.c,
gcc.c-torture/compile/20081108-2.c,
gcc.c-torture/compile/20081108-3.c, gcc.dg/bconstp-2.c,
gcc.dg/bconstp-3.c, gcc.dg/bconstp-4.c, gcc.dg/c90-const-expr-6.c,
gcc.dg/c90-const-expr-7.c, gcc.dg/c90-const-expr-8.c,
gcc.dg/c90-const-expr-9.c, gcc.dg/c90-const-expr-10.c,
gcc.dg/c90-const-expr-11.c, gcc.dg/c99-const-expr-6.c,
gcc.dg/c99-const-expr-7.c, gcc.dg/c99-const-expr-8.c,
gcc.dg/c99-const-expr-9.c, gcc.dg/c99-const-expr-10.c,
gcc.dg/c99-const-expr-11.c, gcc.dg/c99-const-expr-12.c,
gcc.dg/c99-const-expr-13.c, gcc.dg/compare10.c,
gcc.dg/gnu89-const-expr-1.c, gcc.dg/gnu89-const-expr-2.c,
gcc.dg/gnu99-const-expr-1.c, gcc.dg/gnu99-const-expr-2.c,
gcc.dg/gnu99-const-expr-3.c, gcc.dg/vla-12.c, gcc.dg/vla-13.c,
gcc.dg/vla-14.c, gcc.dg/vla-15.c, gcc.dg/vla-16.c: New tests.
* gcc.dg/c90-const-expr-1.c, gcc.dg/c90-const-expr-2.c,
gcc.dg/c90-const-expr-3.c, gcc.dg/c99-const-expr-2.c,
gcc.dg/c99-const-expr-3.c, gcc.dg/c99-static-1.c: Remove XFAILs.
* gcc.dg/c90-const-expr-2.c: Use ZERO in place of 0 in another
case.
* gcc.dg/overflow-warn-1.c, gcc.dg/overflow-warn-2.c,
gcc.dg/overflow-warn-3.c, gcc.dg/overflow-warn-4.c: Remove
XFAILs. Update expected messages.
* gcc.dg/pr14649-1.c, gcc.dg/pr19984.c, gcc.dg/pr25682.c: Update
expected messages.
* gcc.dg/real-const-1.c: Replace with test from original PR.
* gcc.dg/vect/pr32230.c: Use intermediate cast to __PTRDIFF_TYPE__
when casting from non-constant integer to pointer.
2009-03-29 Richard Guenther <rguenther@suse.de> 2009-03-29 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/forwprop-11.c: New testcase. * gcc.dg/tree-ssa/forwprop-11.c: New testcase.
......
/* Test function call with function designator involving VLA
side-effects does not lead to an ICE. */
void f (void);
void g (void);
void
h (int a, void *b)
{
((void *)(int (*)[++a])b ? f : g) ();
}
/* Test boolean conversion as part of returning unsigned value does
not lead to an ICE. */
_Bool f(unsigned a) { return a & 1; }
/* Test boolean conversion of an overflowing integer return value does
not lead to an ICE. */
_Bool f(void) { return __INT_MAX__ + 1; }
/* As bconstp-1.c, but with the __builtin_constant_p calls
parenthesized. */
/* { dg-do compile } */
/* This test checks that builtin_constant_p can be used safely in
initializers for static data. The macro X() defined below should
be an acceptable initializer expression no matter how complex its
argument is. */
extern int a;
extern int b;
extern int foo(void);
extern int bar(void);
#define X(exp) ((__builtin_constant_p(exp)) ? (exp) : -1)
const short tests[] = {
X(0),
X(a),
X(0 && a),
X(a && b),
X(foo()),
X(0 && foo()),
X(a && foo()),
X(foo() && bar())
};
/* As bconstp-1.c, but with the __builtin_constant_p calls inside
__builtin_choose_expr. */
/* { dg-do compile } */
/* This test checks that builtin_constant_p can be used safely in
initializers for static data. The macro X() defined below should
be an acceptable initializer expression no matter how complex its
argument is. */
extern int a;
extern int b;
extern int foo(void);
extern int bar(void);
#define X(exp) (__builtin_choose_expr(1, __builtin_constant_p(exp), 1) ? (exp) : -1)
const short tests[] = {
X(0),
X(a),
X(0 && a),
X(a && b),
X(foo()),
X(0 && foo()),
X(a && foo()),
X(foo() && bar())
};
/* Test that a condition is not counted as a call to
__builtin_constant_p if that call is itself inside a conditional
expression with __builtin_constant_p condition. */
/* { dg-do compile } */
extern int foo(void);
#define X(exp) (__builtin_choose_expr(1, __builtin_constant_p(exp), 1) ? (exp) : -1)
const int x = ((__builtin_constant_p(1) ? __builtin_constant_p (0 && foo()) : 0) ? (0 && foo()) : -1); /* { dg-error "initializer element is not a constant expression" } */
...@@ -15,9 +15,9 @@ void ...@@ -15,9 +15,9 @@ void
foo (void) foo (void)
{ {
int i; int i;
static int j = (1 ? 0 : (i = 2)); /* { dg-error "initial" "assignment" { xfail *-*-* } } */ static int j = (1 ? 0 : (i = 2)); /* { dg-error "initial" "assignment" } */
static int k = (1 ? 0 : ++i); /* { dg-error "initial" "increment" { xfail *-*-* } } */ static int k = (1 ? 0 : ++i); /* { dg-error "initial" "increment" } */
static int l = (1 ? 0 : --i); /* { dg-error "initial" "decrement" { xfail *-*-* } } */ static int l = (1 ? 0 : --i); /* { dg-error "initial" "decrement" } */
static int m = (1 ? 0 : bar ()); /* { dg-error "initial" "function call" { xfail *-*-* } } */ static int m = (1 ? 0 : bar ()); /* { dg-error "initial" "function call" } */
static int n = (1 ? 0 : (2, 3)); /* { dg-error "initial" "comma" { xfail *-*-* } } */ static int n = (1 ? 0 : (2, 3)); /* { dg-error "initial" "comma" } */
} }
/* Test for constant expressions: invalid null pointer constants in
various contexts (make sure NOPs are not inappropriately
stripped). */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
void *p = (__SIZE_TYPE__)(void *)0; /* { dg-error "without a cast" } */
struct s { void *a; } q = { (__SIZE_TYPE__)(void *)0 }; /* { dg-error "without a cast" } */
void *
f (void)
{
void *r;
r = (__SIZE_TYPE__)(void *)0; /* { dg-error "without a cast" } */
return (__SIZE_TYPE__)(void *)0; /* { dg-error "without a cast" } */
}
void g (void *); /* { dg-message "but argument is of type" } */
void
h (void)
{
g ((__SIZE_TYPE__)(void *)0); /* { dg-error "without a cast" } */
}
void g2 (int, void *); /* { dg-message "but argument is of type" } */
void
h2 (void)
{
g2 (0, (__SIZE_TYPE__)(void *)0); /* { dg-error "without a cast" } */
}
/* Test for constant expressions: C90 aggregate initializers requiring
constant expressions. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors -O2" } */
#include <float.h>
#include <limits.h>
double atan(double);
struct s { double d; };
struct t { int i; };
void
f (void)
{
/* As in PR 14649 for static initializers. */
struct s a = { atan (1.0) }; /* { dg-error "is not a constant expression|near initialization" } */
/* Overflow. */
struct t b = { INT_MAX + 1 }; /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
struct t c = { DBL_MAX }; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 23 } */
/* Bad operator outside sizeof. */
struct s d = { 1 ? 1.0 : atan (a.d) }; /* { dg-error "is not a constant expression|near initialization" } */
}
...@@ -34,10 +34,10 @@ foo (void) ...@@ -34,10 +34,10 @@ foo (void)
{ {
ASSERT_NPC (0); ASSERT_NPC (0);
ASSERT_NPC ((void *)0); ASSERT_NPC ((void *)0);
ASSERT_NOT_NPC ((void *)(void *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(void *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((void *)(char *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(char *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((void *)(0, ZERO)); /* { dg-bogus "incompatible" "bogus null pointer constant" } */ ASSERT_NOT_NPC ((void *)(0, ZERO)); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((void *)(&"Foobar"[0] - &"Foobar"[0])); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(&"Foobar"[0] - &"Foobar"[0])); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
/* This last one is a null pointer constant in C99 only. */ /* This last one is a null pointer constant in C99 only. */
ASSERT_NOT_NPC ((void *)(1 ? 0 : (0, 0))); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(1 ? ZERO : (0, ZERO))); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
} }
...@@ -28,19 +28,19 @@ foo (void) ...@@ -28,19 +28,19 @@ foo (void)
ASSERT_NPC (0); ASSERT_NPC (0);
ASSERT_NOT_NPC (ZERO); ASSERT_NOT_NPC (ZERO);
ASSERT_NPC (0 + 0); ASSERT_NPC (0 + 0);
ASSERT_NOT_NPC (ZERO + 0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (ZERO + 0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC (ZERO + ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (ZERO + ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NPC (+0); ASSERT_NPC (+0);
ASSERT_NOT_NPC (+ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (+ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NPC (-0); ASSERT_NPC (-0);
ASSERT_NOT_NPC (-ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (-ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NPC ((char) 0); ASSERT_NPC ((char) 0);
ASSERT_NOT_NPC ((char) ZERO); ASSERT_NOT_NPC ((char) ZERO);
ASSERT_NPC ((int) 0); ASSERT_NPC ((int) 0);
ASSERT_NOT_NPC ((int) ZERO); ASSERT_NOT_NPC ((int) ZERO);
ASSERT_NPC ((int) 0.0); ASSERT_NPC ((int) 0.0);
ASSERT_NOT_NPC ((int) DZERO); ASSERT_NOT_NPC ((int) DZERO);
ASSERT_NOT_NPC ((int) +0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((int) +0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((int) (0.0+0.0)); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((int) (0.0+0.0)); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((int) (double)0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((int) (double)0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
} }
/* Test for constant expressions: operands and casts not permitted in
integer constant expressions. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
/* PR 29116. */
int n = 0, p[n * 0 + 1]; /* { dg-error "variabl|can't be evaluated" } */
/* PR 31871. */
extern int c[1 + ((__PTRDIFF_TYPE__) (void *) 0)]; /* { dg-error "variab|can't be evaluated" } */
/* Implicit conversions from floating-point constants are not OK,
although explicit ones are. */
extern int c1[1.0 ? 1 : 0]; /* { dg-error "variab|can't be evaluated" } */
extern int c2[(int)1.0 ? 1 : 0];
extern int c3[1.0 && 1]; /* { dg-error "variab|can't be evaluated" } */
extern int c4[(int)1.0 && 1];
extern int c5[1.0 || 1]; /* { dg-error "variab|can't be evaluated" } */
extern int c6[(int)1.0 || 1];
/* Similar with various other cases where integer constant expressions
are required. */
struct s {
int a : (n * 0 + 1); /* { dg-error "constant" } */
};
enum e {
E = (1 + ((__PTRDIFF_TYPE__) (void *) 0)), /* { dg-error "constant" } */
E2 = 0
};
enum f {
F = (1 ? 1 : n), /* { dg-error "constant" } */
F2 = 0
};
void
f (int a)
{
int v[1 + ((__PTRDIFF_TYPE__) (void *) 0)]; /* { dg-error "variab|can't be evaluated" } */
switch (a)
{
case (n * 0 + 1): /* { dg-error "constant" } */
;
}
}
/* Test for constant expressions: overflow and constant expressions;
see also overflow-warn-*.c for some other cases. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
#include <float.h>
int a = DBL_MAX; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 9 } */
int b = (int) DBL_MAX; /* { dg-error "overflow" "" } */
unsigned int c = -1.0; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 12 } */
unsigned int d = (unsigned)-1.0; /* { dg-error "overflow" } */
int e = 0 << 1000; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 16 } */
int f = 0 << -1; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 18 } */
int g = 0 >> 1000; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 20 } */
int h = 0 >> -1; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 22 } */
int b1 = (0 ? (int) DBL_MAX : 0);
unsigned int d1 = (0 ? (unsigned int)-1.0 : 0);
int e1 = (0 ? 0 << 1000 : 0);
int f1 = (0 ? 0 << -1 : 0);
int g1 = (0 ? 0 >> 1000 : 0);
int h1 = (0 ? 0 >> -1: 0);
int i = -1 << 0;
int j[1] = { DBL_MAX }; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 34 } */
/* Test for constant expressions: overflow and constant expressions
with -fwrapv: overflows still count as such for the purposes of
constant expressions even when they have defined values at
runtime. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors -fwrapv" } */
#include <limits.h>
enum e {
E0 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 12 } */
E1 = 0 * (INT_MIN / -1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 14 } */
E2 = 0 * (INT_MAX * INT_MAX), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 16 } */
E3 = 0 * (INT_MIN - 1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 18 } */
E4 = 0 * (unsigned)(INT_MIN - 1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 20 } */
E5 = 0 * -INT_MIN, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 22 } */
E6 = 0 * !-INT_MIN, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "not an integer constant" "constant" { target *-*-* } 24 } */
E7 = INT_MIN % -1 /* Not an overflow. */
};
/* Test for constant expressions: __builtin_offsetof allowed in
integer constant expressions but not traditional offsetof
expansion. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
struct s {
int a;
};
struct t {
struct s a;
int b[2];
};
#define old_offsetof(TYPE, MEMBER) ((__SIZE_TYPE__) &((TYPE *)0)->MEMBER)
enum e {
E1 = old_offsetof (struct s, a), /* { dg-error "constant" } */
E2 = old_offsetof (struct t, a.a), /* { dg-error "constant" } */
E3 = old_offsetof (struct t, b[1]), /* { dg-error "constant" } */
E4 = __builtin_offsetof (struct s, a),
E5 = __builtin_offsetof (struct t, a.a),
E6 = __builtin_offsetof (struct t, b[1])
};
/* Test for constant expressions: invalid null pointer constants in
various contexts (make sure NOPs are not inappropriately
stripped). */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
void *p = (__SIZE_TYPE__)(void *)0; /* { dg-error "without a cast" } */
struct s { void *a; } q = { (__SIZE_TYPE__)(void *)0 }; /* { dg-error "without a cast" } */
void *
f (void)
{
void *r;
r = (__SIZE_TYPE__)(void *)0; /* { dg-error "without a cast" } */
return (__SIZE_TYPE__)(void *)0; /* { dg-error "without a cast" } */
}
void g (void *); /* { dg-message "but argument is of type" } */
void
h (void)
{
g ((__SIZE_TYPE__)(void *)0); /* { dg-error "without a cast" } */
}
void g2 (int, void *); /* { dg-message "but argument is of type" } */
void
h2 (void)
{
g2 (0, (__SIZE_TYPE__)(void *)0); /* { dg-error "without a cast" } */
}
/* Test for constant expressions: cases involving VLAs. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
/* It appears address constants may contain casts to variably modified
types. Whether they should be permitted was discussed in
<http://groups.google.com/group/comp.std.c/msg/923eee5ab690fd98>
<LV7g2Vy3ARF$Ew9Q@romana.davros.org>; since static pointers to VLAs
are definitely permitted within functions and may be initialized
and such initialization involves implicit conversion to a variably
modified type, allowing explicit casts seems appropriate. Thus,
GCC allows them as long as the "evaluated" size expressions do not
contain the various operators not permitted to be evaluated in a
constant expression, and as long as the result is genuinely
constant (meaning that pointer arithmetic using the size of the VLA
is generally not permitted). */
static int sa[100];
volatile int nv;
int
f (int m, int n)
{
static int (*a1)[n] = &sa;
static int (*a2)[n] = (int (*)[n])sa;
static int (*a3)[n] = (int (*)[(int){n}])sa;
static int (*a4)[n] = (int (*)[(int){m++}])sa; /* { dg-error "constant" } */
static int (*a5)[n] = (int (*)[(int){++m}])sa; /* { dg-error "constant" } */
static int (*a6)[n] = (int (*)[(int){m--}])sa; /* { dg-error "constant" } */
static int (*a7)[n] = (int (*)[(int){--m}])sa; /* { dg-error "constant" } */
static int (*a8)[n] = (int (*)[(m=n)])sa; /* { dg-error "constant" } */
static int (*a9)[n] = (int (*)[(m+=n)])sa; /* { dg-error "constant" } */
static int (*a10)[n] = (int (*)[f(m,n)])sa; /* { dg-error "constant" } */
static int (*a11)[n] = (int (*)[(m,n)])sa; /* { dg-error "constant" } */
static int (*a12)[n] = (int (*)[sizeof(int[n])])sa;
static int (*a13)[n] = (int (*)[sizeof(int[m++])])sa; /* { dg-error "constant" } */
static int (*a14)[n] = (int (*)[sizeof(*a1)])sa;
static int (*a15)[n] = (int (*)[sizeof(*(int (*)[n])sa)])sa;
static int (*a16)[n] = (int (*)[sizeof(*(int (*)[m++])sa)])sa; /* { dg-error "constant" } */
static int (*a17)[n] = (int (*)[nv])sa;
typedef int (*vmt)[m++];
static int (*a18)[n] = (vmt)sa;
return n;
}
/* Test for constant expressions: VLA size constraints. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
void
f (int m)
{
/* An array size that is a constant expression, not just an integer
constant expression, must be checked for being positive, but only
an integer constant expression makes it not a VLA (which affects
certain compatibility checks, in particular). */
int a1[0]; /* { dg-error "zero" } */
int a2[-1]; /* { dg-error "negative" } */
int a3[(int)(double)0.0]; /* { dg-error "zero" } */
int a4[(int)-1.0]; /* { dg-error "negative" } */
int a5[(int)+1.0];
int a6[(int)+2.0];
void *p = (m ? &a5 : &a6);
int a7[(int)1.0];
int a8[(int)2.0];
void *q = (m ? &a7 : &a8); /* { dg-error "pointer type mismatch in conditional expression" } */
}
/* Test for constant expressions: VLA size constraints with
-frounding-math. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors -frounding-math" } */
void
f (void)
{
/* With -frounding-math, presume that floating-point expressions
that may depend on the rounding mode do not count as arithmetic
constant expressions, and so arrays involving such expressions in
their sizes do not have the size checked for being negative. */
int a1[(int)(-5.0/3.0)];
}
...@@ -34,10 +34,10 @@ foo (void) ...@@ -34,10 +34,10 @@ foo (void)
{ {
ASSERT_NPC (0); ASSERT_NPC (0);
ASSERT_NPC ((void *)0); ASSERT_NPC ((void *)0);
ASSERT_NOT_NPC ((void *)(void *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(void *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((void *)(char *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(char *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((void *)(0, ZERO)); /* { dg-bogus "incompatible" "bogus null pointer constant" } */ ASSERT_NOT_NPC ((void *)(0, ZERO)); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((void *)(&"Foobar"[0] - &"Foobar"[0])); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((void *)(&"Foobar"[0] - &"Foobar"[0])); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
/* This last one is a null pointer constant in C99 only. */ /* This last one is a null pointer constant in C99 only. */
ASSERT_NPC ((void *)(1 ? 0 : (0, 0))); ASSERT_NPC ((void *)(1 ? 0 : (0, 0)));
} }
...@@ -27,19 +27,19 @@ foo (void) ...@@ -27,19 +27,19 @@ foo (void)
ASSERT_NPC (0); ASSERT_NPC (0);
ASSERT_NOT_NPC (ZERO); ASSERT_NOT_NPC (ZERO);
ASSERT_NPC (0 + 0); ASSERT_NPC (0 + 0);
ASSERT_NOT_NPC (ZERO + 0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (ZERO + 0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC (ZERO + ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (ZERO + ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NPC (+0); ASSERT_NPC (+0);
ASSERT_NOT_NPC (+ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (+ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NPC (-0); ASSERT_NPC (-0);
ASSERT_NOT_NPC (-ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC (-ZERO); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NPC ((char) 0); ASSERT_NPC ((char) 0);
ASSERT_NOT_NPC ((char) ZERO); ASSERT_NOT_NPC ((char) ZERO);
ASSERT_NPC ((int) 0); ASSERT_NPC ((int) 0);
ASSERT_NOT_NPC ((int) ZERO); ASSERT_NOT_NPC ((int) ZERO);
ASSERT_NPC ((int) 0.0); ASSERT_NPC ((int) 0.0);
ASSERT_NOT_NPC ((int) DZERO); ASSERT_NOT_NPC ((int) DZERO);
ASSERT_NOT_NPC ((int) +0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((int) +0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((int) (0.0+0.0)); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((int) (0.0+0.0)); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
ASSERT_NOT_NPC ((int) (double)0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */ ASSERT_NOT_NPC ((int) (double)0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
} }
/* Test for constant expressions: operands and casts not permitted in
integer constant expressions. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
/* PR 29116. */
int n = 0, p[n * 0 + 1]; /* { dg-error "variabl" } */
/* PR 31871. */
extern int c[1 + ((__PTRDIFF_TYPE__) (void *) 0)]; /* { dg-error "variab" } */
/* Implicit conversions from floating-point constants are not OK,
although explicit ones are. */
extern int c1[1.0 ? 1 : 0]; /* { dg-error "variab" } */
extern int c2[(int)1.0 ? 1 : 0];
extern int c3[1.0 && 1]; /* { dg-error "variab" } */
extern int c4[(int)1.0 && 1];
extern int c5[1.0 || 1]; /* { dg-error "variab" } */
extern int c6[(int)1.0 || 1];
/* Similar with various other cases where integer constant expressions
are required. */
struct s {
int a : (n * 0 + 1); /* { dg-error "constant" } */
};
enum e {
E = (1 + ((__PTRDIFF_TYPE__) (void *) 0)), /* { dg-error "constant" } */
E2 = 0
};
enum f {
F = (1 ? 1 : n), /* { dg-error "constant" } */
F2 = 0
};
/* Presume that a compound literal, being a reference to an anonymous
variable, is not allowed in an integer constant expression
regardless of what initializers it contains. */
enum g {
G = (1 ? 1 : (int){0}), /* { dg-error "constant" } */
G2 = 0
};
int v[2] = { [(n * 0 + 1)] = 1 }; /* { dg-error "constant|near initialization" } */
void
f (int a)
{
switch (a)
{
case (n * 0 + 1): /* { dg-error "constant" } */
;
}
}
/* Test for constant expressions: overflow and constant expressions;
see also overflow-warn-*.c for some other cases. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
#include <float.h>
#include <limits.h>
int a = DBL_MAX; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 10 } */
int b = (int) DBL_MAX; /* { dg-error "overflow" "" } */
unsigned int c = -1.0; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 13 } */
unsigned int d = (unsigned)-1.0; /* { dg-error "overflow" } */
int e = 0 << 1000; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 17 } */
int f = 0 << -1; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 19 } */
int g = 0 >> 1000; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 21 } */
int h = 0 >> -1; /* { dg-warning "shift count" } */
/* { dg-error "constant" "constant" { target *-*-* } 23 } */
int b1 = (0 ? (int) DBL_MAX : 0);
unsigned int d1 = (0 ? (unsigned int)-1.0 : 0);
int e1 = (0 ? 0 << 1000 : 0);
int f1 = (0 ? 0 << -1 : 0);
int g1 = (0 ? 0 >> 1000 : 0);
int h1 = (0 ? 0 >> -1: 0);
/* Allowed for now, but actually undefined behavior in C99. */
int i = -1 << 0;
int j[1] = { DBL_MAX }; /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 36 } */
int array[2] = { [0 * (INT_MAX + 1)] = 0 }; /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 39 } */
_Bool k = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 42 } */
/* Test for constant expressions: overflow and constant expressions
with -fwrapv: overflows still count as such for the purposes of
constant expressions even when they have defined values at
runtime. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors -fwrapv" } */
#include <limits.h>
enum e {
E0 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 12 } */
E1 = 0 * (INT_MIN / -1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 14 } */
E2 = 0 * (INT_MAX * INT_MAX), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 16 } */
E3 = 0 * (INT_MIN - 1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 18 } */
E4 = 0 * (unsigned)(INT_MIN - 1), /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 20 } */
E5 = 0 * -INT_MIN, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 22 } */
E6 = 0 * !-INT_MIN, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "not an integer constant" "constant" { target *-*-* } 24 } */
E7 = INT_MIN % -1 /* Not an overflow. */
};
/* Test for constant expressions: __builtin_offsetof allowed in
integer constant expressions but not traditional offsetof
expansion. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
struct s {
int a;
};
struct t {
struct s a;
int b[2];
};
#define old_offsetof(TYPE, MEMBER) ((__SIZE_TYPE__) &((TYPE *)0)->MEMBER)
enum e {
E1 = old_offsetof (struct s, a), /* { dg-error "constant" } */
E2 = old_offsetof (struct t, a.a), /* { dg-error "constant" } */
E3 = old_offsetof (struct t, b[1]), /* { dg-error "constant" } */
E4 = __builtin_offsetof (struct s, a),
E5 = __builtin_offsetof (struct t, a.a),
E6 = __builtin_offsetof (struct t, b[1])
};
...@@ -27,7 +27,7 @@ static int f4(void); ...@@ -27,7 +27,7 @@ static int f4(void);
void g4(void) { sizeof(int (*)[f4()]); } void g4(void) { sizeof(int (*)[f4()]); }
/* Constraint violation (VLA). */ /* Constraint violation (VLA). */
static int f5(void); /* { dg-error "used but never defined" "VLA" { xfail *-*-* } } */ static int f5(void); /* { dg-error "used but never defined" "VLA" } */
void g5(void) { sizeof(int [0 ? f5() : 1]); } void g5(void) { sizeof(int [0 ? f5() : 1]); }
/* OK (non-constant sizeof inside constant sizeof). */ /* OK (non-constant sizeof inside constant sizeof). */
......
/* Test for bogus -Wsign-compare warnings that appeared when not
folding operands before warning. */
/* { dg-do compile } */
/* { dg-options "-Wsign-compare" } */
int
test_compare (int a, unsigned b)
{
return (b > 8 * (a ? 4 : 8));
}
unsigned int
test_conditional (int a, unsigned b, int c)
{
return (c ? b : 8 * (a ? 4 : 8));
}
/* Test for constant expressions: GNU extensions. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu89" } */
int n;
void
f (void)
{
int i = 0;
int a[n];
enum e1 {
/* Integer constant expressions may not contain statement
expressions (not a permitted operand). */
E1 = (1 ? 0 : ({ 0; })), /* { dg-error "constant" } */
/* Real and imaginary parts act like other arithmetic
operators. */
E2 = __real__ (1 ? 0 : i++), /* { dg-error "constant" } */
E3 = __real__ 0,
E4 = __imag__ (1 ? 0 : i++), /* { dg-error "constant" } */
E5 = __imag__ 0,
/* __alignof__ always constant. */
E6 = __alignof__ (int[n]),
E7 = __alignof__ (a),
/* __extension__ ignored for constant expression purposes. */
E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant" } */
E9 = __extension__ 0,
/* Conditional expressions with omitted arguments act like the
standard type. */
E10 = (1 ? : i++), /* { dg-error "constant" } */
E11 = (1 ? : 0)
};
enum e2 {
/* Complex integer constants may be cast directly to integer
types, but not after further arithmetic on them. */
F1 = (int) (_Complex int) 2i, /* { dg-error "constant" } */
F2 = (int) +2i, /* { dg-error "constant" } */
F3 = (int) (1 + 2i), /* { dg-error "constant" } */
F4 = (int) 2i
};
static double dr = __real__ (1.0 + 2.0i);
static double di = __imag__ (1.0 + 2.0i);
/* Statement expressions allowed in unevaluated subexpressions in
initializers in gnu99 but not gnu89. */
static int j = (1 ? 0 : ({ 0; })); /* { dg-warning "constant expression" } */
}
/* Test for constant expressions: __builtin_choose_expr. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu89 -pedantic-errors" } */
#include <limits.h>
int a, b, c;
void
f (void)
{
/* __builtin_choose_expr acts exactly like the chosen argument for
all constant expression purposes. */
enum e {
E1 = __builtin_choose_expr (1, 1, ++b)
};
/* The first argument to __builtin_choose_expr must be an integer
constant expression. */
a = __builtin_choose_expr ((void *)0, b, c); /* { dg-error "constant" } */
a = __builtin_choose_expr (0 * (INT_MAX + 1), b, c); /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
}
/* Test for constant expressions: GNU extensions. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
int n;
void
f (void)
{
int i = 0;
int a[n];
enum e1 {
/* Integer constant expressions may not contain statement
expressions (not a permitted operand). */
E1 = (1 ? 0 : ({ 0; })), /* { dg-error "constant" } */
/* Real and imaginary parts act like other arithmetic
operators. */
E2 = __real__ (1 ? 0 : i++), /* { dg-error "constant" } */
E3 = __real__ 0,
E4 = __imag__ (1 ? 0 : i++), /* { dg-error "constant" } */
E5 = __imag__ 0,
/* __alignof__ always constant. */
E6 = __alignof__ (int[n]),
E7 = __alignof__ (a),
/* __extension__ ignored for constant expression purposes. */
E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant" } */
E9 = __extension__ 0,
/* Conditional expressions with omitted arguments act like the
standard type. */
E10 = (1 ? : i++), /* { dg-error "constant" } */
E11 = (1 ? : 0)
};
enum e2 {
/* Complex integer constants may be cast directly to integer
types, but not after further arithmetic on them. */
F1 = (int) (_Complex int) 2i, /* { dg-error "constant" } */
F2 = (int) +2i, /* { dg-error "constant" } */
F3 = (int) (1 + 2i), /* { dg-error "constant" } */
F4 = (int) 2i
};
static double dr = __real__ (1.0 + 2.0i);
static double di = __imag__ (1.0 + 2.0i);
/* Statement expressions allowed in unevaluated subexpressions in
initializers in gnu99 but not gnu89. */
static int j = (1 ? 0 : ({ 0; }));
}
/* Test for constant expressions: __builtin_choose_expr. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -pedantic-errors" } */
#include <limits.h>
int a, b, c;
void
f (void)
{
/* __builtin_choose_expr acts exactly like the chosen argument for
all constant expression purposes. */
enum e {
E1 = __builtin_choose_expr (1, 1, ++b)
};
/* The first argument to __builtin_choose_expr must be an integer
constant expression. */
a = __builtin_choose_expr ((void *)0, b, c); /* { dg-error "constant" } */
a = __builtin_choose_expr (0 * (INT_MAX + 1), b, c); /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
}
/* Test for constant expressions: cases involving VLAs and typeof. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -pedantic-errors" } */
/* It appears address constants may contain casts to variably modified
types. Whether they should be permitted was discussed in
<http://groups.google.com/group/comp.std.c/msg/923eee5ab690fd98>
<LV7g2Vy3ARF$Ew9Q@romana.davros.org>; since static pointers to VLAs
are definitely permitted within functions and may be initialized
and such initialization involves implicit conversion to a variably
modified type, allowing explicit casts seems appropriate. Thus,
GCC allows them as long as the "evaluated" size expressions do not
contain the various operators not permitted to be evaluated in a
constant expression, and as long as the result is genuinely
constant (meaning that pointer arithmetic using the size of the VLA
is generally not permitted). */
static int sa[100];
int
f (int m, int n)
{
static int (*a1)[n] = &sa;
static int (*a2)[n] = (__typeof__(int (*)[n]))sa;
static int (*a3)[n] = (__typeof__(int (*)[(int){m++}]))sa; /* { dg-error "constant" } */
static int (*a4)[n] = (__typeof__((int (*)[n])sa))sa;
static int (*a5)[n] = (__typeof__((int (*)[m++])sa))sa; /* { dg-error "constant" } */
static int (*a6)[n] = (__typeof__((int (*)[100])(int (*)[m++])sa))sa;
static int (*a7)[n] = (__typeof__((int (*)[n])sa + m++))sa; /* { dg-error "constant" } */
return n;
}
...@@ -17,7 +17,7 @@ enum e { ...@@ -17,7 +17,7 @@ enum e {
/* But as in DR#031, the 1/0 in an evaluated subexpression means the /* But as in DR#031, the 1/0 in an evaluated subexpression means the
whole expression violates the constraints. */ whole expression violates the constraints. */
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target *-*-* } 19 } */
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* Again, overflow in evaluated subexpression. */ /* Again, overflow in evaluated subexpression. */
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */ E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
...@@ -28,6 +28,7 @@ enum e { ...@@ -28,6 +28,7 @@ enum e {
struct s { struct s {
int a; int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "not an integer constant" "integer constant" { target *-*-* } 30 } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
}; };
...@@ -46,9 +47,10 @@ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } ...@@ -46,9 +47,10 @@ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" }
constants. The third has the overflow in an unevaluated constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */ subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 48 } */ /* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 49 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { xfail *-*-* } 50 } */ /* { dg-error "initializer element is not constant" "constant" { target *-*-* } 51 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 51 } */
void *r = (1 ? 0 : INT_MAX+1); void *r = (1 ? 0 : INT_MAX+1);
void void
...@@ -57,6 +59,7 @@ g (int i) ...@@ -57,6 +59,7 @@ g (int i)
switch (i) switch (i)
{ {
case 0 * (1/0): /* { dg-warning "division by zero" } */ case 0 * (1/0): /* { dg-warning "division by zero" } */
/* { dg-error "case label does not reduce to an integer constant" "constant" { target *-*-* } 61 } */
; ;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
; ;
......
...@@ -17,7 +17,7 @@ enum e { ...@@ -17,7 +17,7 @@ enum e {
/* But as in DR#031, the 1/0 in an evaluated subexpression means the /* But as in DR#031, the 1/0 in an evaluated subexpression means the
whole expression violates the constraints. */ whole expression violates the constraints. */
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target *-*-* } 19 } */
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* Again, overflow in evaluated subexpression. */ /* Again, overflow in evaluated subexpression. */
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */ E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
...@@ -28,6 +28,7 @@ enum e { ...@@ -28,6 +28,7 @@ enum e {
struct s { struct s {
int a; int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "not an integer constant" "integer constant" { target *-*-* } 30 } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
}; };
...@@ -46,9 +47,10 @@ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } ...@@ -46,9 +47,10 @@ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" }
constants. The third has the overflow in an unevaluated constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */ subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 48 } */ /* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 49 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { xfail *-*-* } 50 } */ /* { dg-error "initializer element is not constant" "constant" { target *-*-* } 51 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 51 } */
void *r = (1 ? 0 : INT_MAX+1); void *r = (1 ? 0 : INT_MAX+1);
void void
...@@ -57,6 +59,7 @@ g (int i) ...@@ -57,6 +59,7 @@ g (int i)
switch (i) switch (i)
{ {
case 0 * (1/0): /* { dg-warning "division by zero" } */ case 0 * (1/0): /* { dg-warning "division by zero" } */
/* { dg-error "case label does not reduce to an integer constant" "constant" { target *-*-* } 61 } */
; ;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
; ;
...@@ -82,23 +85,23 @@ void ...@@ -82,23 +85,23 @@ void
h2 (void) h2 (void)
{ {
fsc (SCHAR_MAX + 1); fsc (SCHAR_MAX + 1);
/* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 84 } */ /* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 87 } */
fsc (SCHAR_MIN - 1); /* { dg-warning "overflow in implicit constant conversion" } */ fsc (SCHAR_MIN - 1); /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 86 } */ /* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 89 } */
fsc (UCHAR_MAX); fsc (UCHAR_MAX);
/* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 88 } */ /* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 91 } */
fsc (UCHAR_MAX + 1); /* { dg-warning "overflow in implicit constant conversion" } */ fsc (UCHAR_MAX + 1); /* { dg-warning "overflow in implicit constant conversion" } */
/* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 90 } */ /* { dg-warning "passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 93 } */
fuc (-1); fuc (-1);
/* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 92 } */ /* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 95 } */
fuc (UCHAR_MAX + 1); /* { dg-warning "large integer implicitly truncated to unsigned type" } */ fuc (UCHAR_MAX + 1); /* { dg-warning "large integer implicitly truncated to unsigned type" } */
/* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 94 } */ /* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 97 } */
fuc (SCHAR_MIN); fuc (SCHAR_MIN);
/* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 96 } */ /* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 99 } */
fuc (SCHAR_MIN - 1); /* { dg-warning "large integer implicitly truncated to unsigned type" } */ fuc (SCHAR_MIN - 1); /* { dg-warning "large integer implicitly truncated to unsigned type" } */
/* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 98 } */ /* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 101 } */
fuc (-UCHAR_MAX); /* { dg-warning "large integer implicitly truncated to unsigned type" } */ fuc (-UCHAR_MAX); /* { dg-warning "large integer implicitly truncated to unsigned type" } */
/* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 100 } */ /* { dg-warning "passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 103 } */
} }
void fui (unsigned int); void fui (unsigned int);
...@@ -122,11 +125,11 @@ h2i (int x) ...@@ -122,11 +125,11 @@ h2i (int x)
fsi (UINT_MAX); /* { dg-warning "passing argument 1 of 'fsi' as signed due to prototype" } */ fsi (UINT_MAX); /* { dg-warning "passing argument 1 of 'fsi' as signed due to prototype" } */
si = UINT_MAX; si = UINT_MAX;
fui (-1); fui (-1);
/* { dg-warning "passing argument 1 of 'fui' as unsigned due to prototype" "-Wtraditional-conversion" { target *-*-* } 124 } */ /* { dg-warning "passing argument 1 of 'fui' as unsigned due to prototype" "-Wtraditional-conversion" { target *-*-* } 127 } */
ui = -1; ui = -1;
ui = x ? -1 : 1U; ui = x ? -1 : 1U;
fui (INT_MIN); fui (INT_MIN);
/* { dg-warning "passing argument 1 of 'fui' as unsigned due to prototype" "-Wtraditional-conversion" { target *-*-* } 128 } */ /* { dg-warning "passing argument 1 of 'fui' as unsigned due to prototype" "-Wtraditional-conversion" { target *-*-* } 131 } */
ui = INT_MIN; ui = INT_MIN;
ui = x ? INT_MIN : 1U; ui = x ? INT_MIN : 1U;
} }
...@@ -17,7 +17,7 @@ enum e { ...@@ -17,7 +17,7 @@ enum e {
/* But as in DR#031, the 1/0 in an evaluated subexpression means the /* But as in DR#031, the 1/0 in an evaluated subexpression means the
whole expression violates the constraints. */ whole expression violates the constraints. */
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target *-*-* } 19 } */
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
/* Again, overflow in evaluated subexpression. */ /* Again, overflow in evaluated subexpression. */
...@@ -30,8 +30,9 @@ enum e { ...@@ -30,8 +30,9 @@ enum e {
struct s { struct s {
int a; int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "not an integer constant" "integer constant" { target *-*-* } 32 } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 33 } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 34 } */
}; };
void void
...@@ -45,16 +46,17 @@ f (void) ...@@ -45,16 +46,17 @@ f (void)
/* But this expression does need to be constant. */ /* But this expression does need to be constant. */
static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 47 } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 48 } */
/* The first two of these involve overflow, so are not null pointer /* The first two of these involve overflow, so are not null pointer
constants. The third has the overflow in an unevaluated constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */ subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 53 } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 54 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 53 } */ /* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 54 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { xfail *-*-* } 56 } */ /* { dg-error "initializer element is not constant" "constant" { target *-*-* } 57 } */
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 57 } */
void *r = (1 ? 0 : INT_MAX+1); void *r = (1 ? 0 : INT_MAX+1);
void void
...@@ -63,9 +65,10 @@ g (int i) ...@@ -63,9 +65,10 @@ g (int i)
switch (i) switch (i)
{ {
case 0 * (1/0): /* { dg-warning "division by zero" } */ case 0 * (1/0): /* { dg-warning "division by zero" } */
/* { dg-error "case label does not reduce to an integer constant" "constant" { target *-*-* } 67 } */
; ;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 67 } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 70 } */
; ;
} }
} }
......
...@@ -17,7 +17,7 @@ enum e { ...@@ -17,7 +17,7 @@ enum e {
/* But as in DR#031, the 1/0 in an evaluated subexpression means the /* But as in DR#031, the 1/0 in an evaluated subexpression means the
whole expression violates the constraints. */ whole expression violates the constraints. */
E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
/* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target *-*-* } 19 } */
E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
/* Again, overflow in evaluated subexpression. */ /* Again, overflow in evaluated subexpression. */
...@@ -30,8 +30,9 @@ enum e { ...@@ -30,8 +30,9 @@ enum e {
struct s { struct s {
int a; int a;
int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ int : 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "not an integer constant" "integer constant" { target *-*-* } 32 } */
int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 33 } */ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 34 } */
}; };
void void
...@@ -45,16 +46,17 @@ f (void) ...@@ -45,16 +46,17 @@ f (void)
/* But this expression does need to be constant. */ /* But this expression does need to be constant. */
static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 47 } */ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 48 } */
/* The first two of these involve overflow, so are not null pointer /* The first two of these involve overflow, so are not null pointer
constants. The third has the overflow in an unevaluated constants. The third has the overflow in an unevaluated
subexpression, so is a null pointer constant. */ subexpression, so is a null pointer constant. */
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 53 } */ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 54 } */
/* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } 53 } */ /* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } 54 } */
void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
/* { dg-error "initialization makes pointer from integer without a cast" "null" { xfail *-*-* } 56 } */ /* { dg-error "initializer element is not constant" "constant" { target *-*-* } 57 } */
/* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } 57 } */
void *r = (1 ? 0 : INT_MAX+1); void *r = (1 ? 0 : INT_MAX+1);
void void
...@@ -63,9 +65,10 @@ g (int i) ...@@ -63,9 +65,10 @@ g (int i)
switch (i) switch (i)
{ {
case 0 * (1/0): /* { dg-warning "division by zero" } */ case 0 * (1/0): /* { dg-warning "division by zero" } */
/* { dg-error "case label does not reduce to an integer constant" "constant" { target *-*-* } 67 } */
; ;
case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 67 } */ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 70 } */
; ;
} }
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
double atan(double); double atan(double);
const double pi = 4*atan(1.0); /* { dg-warning "(not constant)|(near initialization)" } */ const double pi = 4*atan(1.0); /* { dg-warning "not a constant expression" } */
const double ok = 4*__builtin_atan(1.0); const double ok = 4*__builtin_atan(1.0);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
double nan (const char *); double nan (const char *);
const double nok = nan (""); /* { dg-warning "(not constant)|(near initialization)" } */ const double nok = nan (""); /* { dg-warning "(not a constant)|(near initialization)" } */
const double ok = __builtin_nan (""); const double ok = __builtin_nan ("");
......
...@@ -10,10 +10,10 @@ struct S ...@@ -10,10 +10,10 @@ struct S
int b; int b;
}; };
char c[(char *) &((struct S *) 0)->b - (char *) 0]; char c[(char *) &((struct S *) 0)->b - (char *) 0]; /* { dg-error "variable-size" } */
char d[(__SIZE_TYPE__) &((struct S *) 8)->b]; char d[(__SIZE_TYPE__) &((struct S *) 8)->b]; /* { dg-error "variable-size" } */
char e[sizeof (c) == __builtin_offsetof (struct S, b) ? 1 : -1]; char e[sizeof (c) == __builtin_offsetof (struct S, b) ? 1 : -1]; /* { dg-error "variably modified" } */
char f[sizeof (d) == __builtin_offsetof (struct S, b) + 8 ? 1 : -1]; char f[sizeof (d) == __builtin_offsetof (struct S, b) + 8 ? 1 : -1]; /* { dg-error "variably modified" } */
extern void bar (char *, char *); extern void bar (char *, char *);
......
/* PR middle-end/21781. */ /* PR middle-end/21781. */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-Wall" } */
int f[.0e200000000 == 0?1:-1]; int foo(void) { if (.0e200000000 == 0 ) return 1; }
...@@ -16,7 +16,7 @@ const_f (filter_buffer_t *buf) ...@@ -16,7 +16,7 @@ const_f (filter_buffer_t *buf)
int i; int i;
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
((float*) (&((sbuf_header_t *) ((buf) == (filter_buffer_t *)&(buf)->buf[0]))->buf[0]))[i] = val; ((float*) (&((sbuf_header_t *) (__PTRDIFF_TYPE__)((buf) == (filter_buffer_t *)&(buf)->buf[0]))->buf[0]))[i] = val;
} }
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
......
/* Test for typeof evaluation: should be at the appropriate point in
the containing expression rather than just adding a statement. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
extern void exit (int);
extern void abort (void);
void *p;
void
f1 (void)
{
int i = 0, j = -1, k = -1;
/* typeof applied to expression with cast. */
(j = ++i), (void)(typeof ((int (*)[(k = ++i)])p))p;
if (j != 1 || k != 2 || i != 2)
abort ();
}
void
f2 (void)
{
int i = 0, j = -1, k = -1;
/* typeof applied to type. */
(j = ++i), (void)(typeof (int (*)[(k = ++i)]))p;
if (j != 1 || k != 2 || i != 2)
abort ();
}
void
f3 (void)
{
int i = 0, j = -1, k = -1;
void *q;
/* typeof applied to expression with cast that is used. */
(j = ++i), (void)((typeof (1 + (int (*)[(k = ++i)])p))p);
if (j != 1 || k != 2 || i != 2)
abort ();
}
int
main (void)
{
f1 ();
f2 ();
f3 ();
exit (0);
}
/* Test for VLA size evaluation; see PR 35198. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do run } */
/* { dg-options "-std=c99" } */
extern void exit (int);
extern void abort (void);
int i;
void *p;
void
f1 (void *x, int j)
{
p = (int (*)[++i])x;
if (i != j)
abort ();
}
void
f1c (void *x, int j)
{
p = (int (*)[++i]){x};
if (i != j)
abort ();
}
void
f2 (void *x, int j)
{
x = (void *)(int (*)[++i])p;
if (i != j)
abort ();
}
void
f2c (void *x, int j)
{
x = (void *)(int (*)[++i]){p};
if (i != j)
abort ();
}
void
f3 (void *x, int j)
{
(void)(int (*)[++i])p;
if (i != j)
abort ();
}
void
f3c (void *x, int j)
{
(void)(int (*)[++i]){p};
if (i != j)
abort ();
}
void
f4 (void *x, int j)
{
(int (*)[++i])p;
(int (*)[++i])p;
if (i != j)
abort ();
}
void
f4c (void *x, int j)
{
(int (*)[++i]){p};
(int (*)[++i]){p};
if (i != j)
abort ();
}
void
f5c (void *x, int j, int k)
{
(++i, f3c (x, j), (int (*)[++i]){p});
if (i != k)
abort ();
}
int
main (void)
{
f1 (p, 1);
f2 (p, 2);
f3 (p, 3);
f4 (p, 5);
f1c (p, 6);
f2c (p, 7);
f3c (p, 8);
f4c (p, 10);
f5c (p, 12, 13);
exit (0);
}
/* Test for VLA size evaluation in va_arg. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include <stdarg.h>
extern void exit (int);
extern void abort (void);
int a[10];
int i = 9;
void
f (int n, ...)
{
va_list ap;
void *p;
va_start (ap, n);
p = va_arg (ap, typeof (int (*)[++i]));
if (p != a)
abort ();
if (i != n)
abort ();
va_end (ap);
}
int
main (void)
{
f (10, &a);
exit (0);
}
/* Test for VLA size evaluation in sizeof typeof. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include <stdarg.h>
extern void exit (int);
extern void abort (void);
char a[1];
void
f1 (void)
{
int i = 0;
int j = sizeof (typeof (*(++i, (char (*)[i])a)));
if (i != 1 || j != 1)
abort ();
}
int
main (void)
{
f1 ();
exit (0);
}
/* Test for modifying and taking addresses of compound literals whose
variably modified types involve typeof. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do run } */
/* { dg-options "-std=gnu99" } */
#include <stdarg.h>
extern void exit (int);
extern void abort (void);
int a[1];
void
f1 (void)
{
int i = 0;
int (**p)[1] = &(typeof (++i, (int (*)[i])a)){&a};
if (*p != &a)
abort ();
if (i != 1)
abort ();
}
void
f2 (void)
{
int i = 0;
(typeof (++i, (int (*)[i])a)){&a} = 0;
if (i != 1)
abort ();
}
void
f3 (void)
{
int i = 0;
(typeof (++i, (int (*)[i])a)){&a} += 1;
if (i != 1)
abort ();
}
void
f4 (void)
{
int i = 0;
--(typeof (++i, (int (*)[i])a)){&a + 1};
if (i != 1)
abort ();
}
void
f5 (void)
{
int i = 0;
(typeof (++i, (int (*)[i])a)){&a}++;
if (i != 1)
abort ();
}
int
main (void)
{
f1 ();
f2 ();
f3 ();
f4 ();
f5 ();
exit (0);
}
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