mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
5babbcc0fc
commit
928c19bbb0
|
@ -1,3 +1,15 @@
|
|||
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>
|
||||
|
||||
* inclhack.def (aix_syswait, exception_structure,
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
|
@ -15,7 +15,7 @@
|
|||
* 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.
|
||||
*
|
||||
* This file contains 177 fixup descriptions.
|
||||
* This file contains 178 fixup descriptions.
|
||||
*
|
||||
* See README for more information.
|
||||
*
|
||||
|
@ -2217,6 +2217,49 @@ s/{ { 0, } }/{ { 0, 0, 0, 0, 0, 0 } }/\n\
|
|||
"-e", "/define[ \t]\\+PTHREAD_COND_INITIALIZER/s/{ { 0, } }/{ { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }/",
|
||||
(char*)NULL };
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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
|
||||
|
@ -7192,9 +7235,9 @@ static const char* apzX11_SprintfPatch[] = {
|
|||
*
|
||||
* List of all fixes
|
||||
*/
|
||||
#define REGEX_COUNT 221
|
||||
#define REGEX_COUNT 223
|
||||
#define MACH_LIST_SIZE_LIMIT 181
|
||||
#define FIX_COUNT 177
|
||||
#define FIX_COUNT 178
|
||||
|
||||
/*
|
||||
* Enumerate the fixes
|
||||
|
@ -7253,6 +7296,7 @@ typedef enum {
|
|||
GLIBC_C99_INLINE_3_FIXIDX,
|
||||
GLIBC_C99_INLINE_4_FIXIDX,
|
||||
GLIBC_MUTEX_INIT_FIXIDX,
|
||||
GLIBC_TGMATH_FIXIDX,
|
||||
GNU_TYPES_FIXIDX,
|
||||
HP_INLINE_FIXIDX,
|
||||
HP_SYSFILE_FIXIDX,
|
||||
|
@ -7645,6 +7689,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
|
|||
GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY,
|
||||
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,
|
||||
apzGnu_TypesMachs,
|
||||
GNU_TYPES_TEST_CT, FD_MACH_IFNOT | FD_SUBROUTINE,
|
||||
|
|
|
@ -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
|
||||
* ptrdiff_t, size_t, and wchar_t.
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/* 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 */
|
171
gcc/ChangeLog
171
gcc/ChangeLog
|
@ -1,3 +1,174 @@
|
|||
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>
|
||||
|
||||
* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Properly
|
||||
|
|
|
@ -7930,7 +7930,7 @@ fold_builtin_sincos (tree arg0, tree arg1, tree arg2)
|
|||
call = build_call_expr (fn, 1, arg0);
|
||||
call = builtin_save_expr (call);
|
||||
|
||||
return build2 (COMPOUND_EXPR, type,
|
||||
return build2 (COMPOUND_EXPR, void_type_node,
|
||||
build2 (MODIFY_EXPR, void_type_node,
|
||||
build_fold_indirect_ref (arg1),
|
||||
build1 (IMAGPART_EXPR, type, call)),
|
||||
|
@ -10929,7 +10929,6 @@ fold_call_expr (tree exp, bool ignore)
|
|||
if (CAN_HAVE_LOCATION_P (realret)
|
||||
&& !EXPR_HAS_LOCATION (realret))
|
||||
SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp));
|
||||
return realret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
431
gcc/c-common.c
431
gcc/c-common.c
|
@ -518,6 +518,7 @@ const struct fname_var_t fname_vars[] =
|
|||
{NULL, 0, 0},
|
||||
};
|
||||
|
||||
static tree c_fully_fold_internal (tree expr, bool, bool *, bool *);
|
||||
static tree check_case_value (tree);
|
||||
static bool check_case_bounds (tree, tree, tree *, tree *);
|
||||
|
||||
|
@ -1107,6 +1108,390 @@ fix_string_type (tree value)
|
|||
return value;
|
||||
}
|
||||
|
||||
/* Fully fold EXPR, an expression that was not folded (beyond integer
|
||||
constant expressions and null pointer constants) when being built
|
||||
up. If IN_INIT, this is in a static initializer and certain
|
||||
changes are made to the folding done. Clear *MAYBE_CONST if
|
||||
MAYBE_CONST is not NULL and EXPR is definitely not a constant
|
||||
expression because it contains an evaluated operator (in C99) or an
|
||||
operator outside of sizeof returning an integer constant (in C90)
|
||||
not permitted in constant expressions, or because it contains an
|
||||
evaluated arithmetic overflow. (*MAYBE_CONST should typically be
|
||||
set to true by callers before calling this function.) Return the
|
||||
folded expression. Function arguments have already been folded
|
||||
before calling this function, as have the contents of SAVE_EXPR,
|
||||
TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
|
||||
C_MAYBE_CONST_EXPR. */
|
||||
|
||||
tree
|
||||
c_fully_fold (tree expr, bool in_init, bool *maybe_const)
|
||||
{
|
||||
tree ret;
|
||||
bool dummy = true;
|
||||
bool maybe_const_itself = true;
|
||||
|
||||
/* This function is not relevant to C++ because C++ folds while
|
||||
parsing, and may need changes to be correct for C++ when C++
|
||||
stops folding while parsing. */
|
||||
if (c_dialect_cxx ())
|
||||
gcc_unreachable ();
|
||||
|
||||
if (!maybe_const)
|
||||
maybe_const = &dummy;
|
||||
ret = c_fully_fold_internal (expr, in_init, maybe_const,
|
||||
&maybe_const_itself);
|
||||
*maybe_const &= maybe_const_itself;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Internal helper for c_fully_fold. EXPR and IN_INIT are as for
|
||||
c_fully_fold. *MAYBE_CONST_OPERANDS is cleared because of operands
|
||||
not permitted, while *MAYBE_CONST_ITSELF is cleared because of
|
||||
arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from
|
||||
both evaluated and unevaluated subexpressions while
|
||||
*MAYBE_CONST_ITSELF is carried from only evaluated
|
||||
subexpressions). */
|
||||
|
||||
static tree
|
||||
c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
bool *maybe_const_itself)
|
||||
{
|
||||
tree ret = expr;
|
||||
enum tree_code code = TREE_CODE (expr);
|
||||
enum tree_code_class kind = TREE_CODE_CLASS (code);
|
||||
location_t loc = EXPR_LOCATION (expr);
|
||||
tree op0, op1, op2, op3;
|
||||
tree orig_op0, orig_op1, orig_op2;
|
||||
bool op0_const = true, op1_const = true, op2_const = true;
|
||||
bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
|
||||
bool nowarning = TREE_NO_WARNING (expr);
|
||||
|
||||
/* This function is not relevant to C++ because C++ folds while
|
||||
parsing, and may need changes to be correct for C++ when C++
|
||||
stops folding while parsing. */
|
||||
if (c_dialect_cxx ())
|
||||
gcc_unreachable ();
|
||||
|
||||
/* Constants, declarations, statements, errors, SAVE_EXPRs and
|
||||
anything else not counted as an expression cannot usefully be
|
||||
folded further at this point. */
|
||||
if (!IS_EXPR_CODE_CLASS (kind)
|
||||
|| kind == tcc_statement
|
||||
|| code == SAVE_EXPR)
|
||||
return expr;
|
||||
|
||||
/* Operands of variable-length expressions (function calls) have
|
||||
already been folded, as have __builtin_* function calls, and such
|
||||
expressions cannot occur in constant expressions. */
|
||||
if (kind == tcc_vl_exp)
|
||||
{
|
||||
*maybe_const_operands = false;
|
||||
ret = fold (expr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (code == C_MAYBE_CONST_EXPR)
|
||||
{
|
||||
tree pre = C_MAYBE_CONST_EXPR_PRE (expr);
|
||||
tree inner = C_MAYBE_CONST_EXPR_EXPR (expr);
|
||||
if (C_MAYBE_CONST_EXPR_NON_CONST (expr))
|
||||
*maybe_const_operands = false;
|
||||
if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr))
|
||||
*maybe_const_itself = false;
|
||||
if (pre && !in_init)
|
||||
ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
|
||||
else
|
||||
ret = inner;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Assignment, increment, decrement, function call and comma
|
||||
operators, and statement expressions, cannot occur in constant
|
||||
expressions if evaluated / outside of sizeof. (Function calls
|
||||
were handled above, though VA_ARG_EXPR is treated like a function
|
||||
call here, and statement expressions are handled through
|
||||
C_MAYBE_CONST_EXPR to avoid folding inside them.) */
|
||||
switch (code)
|
||||
{
|
||||
case MODIFY_EXPR:
|
||||
case PREDECREMENT_EXPR:
|
||||
case PREINCREMENT_EXPR:
|
||||
case POSTDECREMENT_EXPR:
|
||||
case POSTINCREMENT_EXPR:
|
||||
case COMPOUND_EXPR:
|
||||
*maybe_const_operands = false;
|
||||
break;
|
||||
|
||||
case VA_ARG_EXPR:
|
||||
case TARGET_EXPR:
|
||||
case BIND_EXPR:
|
||||
case OBJ_TYPE_REF:
|
||||
*maybe_const_operands = false;
|
||||
ret = fold (expr);
|
||||
goto out;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fold individual tree codes as appropriate. */
|
||||
switch (code)
|
||||
{
|
||||
case COMPOUND_LITERAL_EXPR:
|
||||
/* Any non-constancy will have been marked in a containing
|
||||
C_MAYBE_CONST_EXPR; there is no more folding to do here. */
|
||||
goto out;
|
||||
|
||||
case COMPONENT_REF:
|
||||
orig_op0 = op0 = TREE_OPERAND (expr, 0);
|
||||
op1 = TREE_OPERAND (expr, 1);
|
||||
op2 = TREE_OPERAND (expr, 2);
|
||||
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
|
||||
maybe_const_itself);
|
||||
if (op0 != orig_op0)
|
||||
ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
|
||||
if (ret != expr)
|
||||
{
|
||||
TREE_READONLY (ret) = TREE_READONLY (expr);
|
||||
TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
|
||||
}
|
||||
goto out;
|
||||
|
||||
case ARRAY_REF:
|
||||
orig_op0 = op0 = TREE_OPERAND (expr, 0);
|
||||
orig_op1 = op1 = TREE_OPERAND (expr, 1);
|
||||
op2 = TREE_OPERAND (expr, 2);
|
||||
op3 = TREE_OPERAND (expr, 3);
|
||||
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
|
||||
maybe_const_itself);
|
||||
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
|
||||
maybe_const_itself);
|
||||
op1 = decl_constant_value_for_optimization (op1);
|
||||
if (op0 != orig_op0 || op1 != orig_op1)
|
||||
ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
|
||||
if (ret != expr)
|
||||
{
|
||||
TREE_READONLY (ret) = TREE_READONLY (expr);
|
||||
TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
|
||||
TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
|
||||
}
|
||||
ret = fold (ret);
|
||||
goto out;
|
||||
|
||||
case COMPOUND_EXPR:
|
||||
case MODIFY_EXPR:
|
||||
case PREDECREMENT_EXPR:
|
||||
case PREINCREMENT_EXPR:
|
||||
case POSTDECREMENT_EXPR:
|
||||
case POSTINCREMENT_EXPR:
|
||||
case PLUS_EXPR:
|
||||
case MINUS_EXPR:
|
||||
case MULT_EXPR:
|
||||
case POINTER_PLUS_EXPR:
|
||||
case TRUNC_DIV_EXPR:
|
||||
case CEIL_DIV_EXPR:
|
||||
case FLOOR_DIV_EXPR:
|
||||
case TRUNC_MOD_EXPR:
|
||||
case RDIV_EXPR:
|
||||
case EXACT_DIV_EXPR:
|
||||
case LSHIFT_EXPR:
|
||||
case RSHIFT_EXPR:
|
||||
case BIT_IOR_EXPR:
|
||||
case BIT_XOR_EXPR:
|
||||
case BIT_AND_EXPR:
|
||||
case LT_EXPR:
|
||||
case LE_EXPR:
|
||||
case GT_EXPR:
|
||||
case GE_EXPR:
|
||||
case EQ_EXPR:
|
||||
case NE_EXPR:
|
||||
case COMPLEX_EXPR:
|
||||
case TRUTH_AND_EXPR:
|
||||
case TRUTH_OR_EXPR:
|
||||
case TRUTH_XOR_EXPR:
|
||||
case UNORDERED_EXPR:
|
||||
case ORDERED_EXPR:
|
||||
case UNLT_EXPR:
|
||||
case UNLE_EXPR:
|
||||
case UNGT_EXPR:
|
||||
case UNGE_EXPR:
|
||||
case UNEQ_EXPR:
|
||||
/* Binary operations evaluating both arguments (increment and
|
||||
decrement are binary internally in GCC). */
|
||||
orig_op0 = op0 = TREE_OPERAND (expr, 0);
|
||||
orig_op1 = op1 = TREE_OPERAND (expr, 1);
|
||||
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
|
||||
maybe_const_itself);
|
||||
if (code != MODIFY_EXPR
|
||||
&& code != PREDECREMENT_EXPR
|
||||
&& code != PREINCREMENT_EXPR
|
||||
&& code != POSTDECREMENT_EXPR
|
||||
&& code != POSTINCREMENT_EXPR)
|
||||
op0 = decl_constant_value_for_optimization (op0);
|
||||
/* The RHS of a MODIFY_EXPR was fully folded when building that
|
||||
expression for the sake of conversion warnings. */
|
||||
if (code != MODIFY_EXPR)
|
||||
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
|
||||
maybe_const_itself);
|
||||
op1 = decl_constant_value_for_optimization (op1);
|
||||
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
|
||||
ret = in_init
|
||||
? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
|
||||
: fold_build2 (code, TREE_TYPE (expr), op0, op1);
|
||||
else
|
||||
ret = fold (expr);
|
||||
goto out;
|
||||
|
||||
case INDIRECT_REF:
|
||||
case FIX_TRUNC_EXPR:
|
||||
case FLOAT_EXPR:
|
||||
CASE_CONVERT:
|
||||
case NON_LVALUE_EXPR:
|
||||
case NEGATE_EXPR:
|
||||
case BIT_NOT_EXPR:
|
||||
case TRUTH_NOT_EXPR:
|
||||
case ADDR_EXPR:
|
||||
case CONJ_EXPR:
|
||||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
/* Unary operations. */
|
||||
orig_op0 = op0 = TREE_OPERAND (expr, 0);
|
||||
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
|
||||
maybe_const_itself);
|
||||
if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
|
||||
op0 = decl_constant_value_for_optimization (op0);
|
||||
if (op0 != orig_op0 || in_init)
|
||||
ret = in_init
|
||||
? fold_build1_initializer (code, TREE_TYPE (expr), op0)
|
||||
: fold_build1 (code, TREE_TYPE (expr), op0);
|
||||
else
|
||||
ret = fold (expr);
|
||||
if (code == INDIRECT_REF
|
||||
&& ret != expr
|
||||
&& TREE_CODE (ret) == INDIRECT_REF)
|
||||
{
|
||||
TREE_READONLY (ret) = TREE_READONLY (expr);
|
||||
TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
|
||||
TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
|
||||
}
|
||||
goto out;
|
||||
|
||||
case TRUTH_ANDIF_EXPR:
|
||||
case TRUTH_ORIF_EXPR:
|
||||
/* Binary operations not necessarily evaluating both
|
||||
arguments. */
|
||||
orig_op0 = op0 = TREE_OPERAND (expr, 0);
|
||||
orig_op1 = op1 = TREE_OPERAND (expr, 1);
|
||||
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
|
||||
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
|
||||
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
|
||||
ret = in_init
|
||||
? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
|
||||
: fold_build2 (code, TREE_TYPE (expr), op0, op1);
|
||||
else
|
||||
ret = fold (expr);
|
||||
*maybe_const_operands &= op0_const;
|
||||
*maybe_const_itself &= op0_const_self;
|
||||
if (!(flag_isoc99
|
||||
&& op0_const
|
||||
&& op0_const_self
|
||||
&& (code == TRUTH_ANDIF_EXPR
|
||||
? op0 == truthvalue_false_node
|
||||
: op0 == truthvalue_true_node)))
|
||||
*maybe_const_operands &= op1_const;
|
||||
if (!(op0_const
|
||||
&& op0_const_self
|
||||
&& (code == TRUTH_ANDIF_EXPR
|
||||
? op0 == truthvalue_false_node
|
||||
: op0 == truthvalue_true_node)))
|
||||
*maybe_const_itself &= op1_const_self;
|
||||
goto out;
|
||||
|
||||
case COND_EXPR:
|
||||
orig_op0 = op0 = TREE_OPERAND (expr, 0);
|
||||
orig_op1 = op1 = TREE_OPERAND (expr, 1);
|
||||
orig_op2 = op2 = TREE_OPERAND (expr, 2);
|
||||
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
|
||||
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
|
||||
op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
|
||||
if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
|
||||
ret = fold_build3 (code, TREE_TYPE (expr), op0, op1, op2);
|
||||
else
|
||||
ret = fold (expr);
|
||||
*maybe_const_operands &= op0_const;
|
||||
*maybe_const_itself &= op0_const_self;
|
||||
if (!(flag_isoc99
|
||||
&& op0_const
|
||||
&& op0_const_self
|
||||
&& op0 == truthvalue_false_node))
|
||||
*maybe_const_operands &= op1_const;
|
||||
if (!(op0_const
|
||||
&& op0_const_self
|
||||
&& op0 == truthvalue_false_node))
|
||||
*maybe_const_itself &= op1_const_self;
|
||||
if (!(flag_isoc99
|
||||
&& op0_const
|
||||
&& op0_const_self
|
||||
&& op0 == truthvalue_true_node))
|
||||
*maybe_const_operands &= op2_const;
|
||||
if (!(op0_const
|
||||
&& op0_const_self
|
||||
&& op0 == truthvalue_true_node))
|
||||
*maybe_const_itself &= op2_const_self;
|
||||
goto out;
|
||||
|
||||
default:
|
||||
/* Various codes may appear through folding built-in functions
|
||||
and their arguments. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
|
||||
have been done by this point, so remove them again. */
|
||||
nowarning |= TREE_NO_WARNING (ret);
|
||||
STRIP_TYPE_NOPS (ret);
|
||||
if (nowarning && !TREE_NO_WARNING (ret))
|
||||
{
|
||||
if (!CAN_HAVE_LOCATION_P (ret))
|
||||
ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
|
||||
TREE_NO_WARNING (ret) = 1;
|
||||
}
|
||||
if (ret != expr)
|
||||
protected_set_expr_location (ret, loc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
|
||||
return EXP. Otherwise, return either EXP or its known constant
|
||||
value (if it has one), but return EXP if EXP has mode BLKmode. ???
|
||||
Is the BLKmode test appropriate? */
|
||||
|
||||
tree
|
||||
decl_constant_value_for_optimization (tree exp)
|
||||
{
|
||||
tree ret;
|
||||
|
||||
/* This function is only used by C, for c_fully_fold and other
|
||||
optimization, and may not be correct for C++. */
|
||||
if (c_dialect_cxx ())
|
||||
gcc_unreachable ();
|
||||
|
||||
if (!optimize
|
||||
|| TREE_CODE (exp) != VAR_DECL
|
||||
|| TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
|
||||
|| DECL_MODE (exp) == BLKmode)
|
||||
return exp;
|
||||
|
||||
ret = decl_constant_value (exp);
|
||||
/* Avoid unwanted tree sharing between the initializer and current
|
||||
function's body where the tree can be modified e.g. by the
|
||||
gimplifier. */
|
||||
if (ret != exp && TREE_STATIC (exp))
|
||||
ret = unshare_expr (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Print a warning if a constant expression had overflow in folding.
|
||||
Invoke this function on every expression that the language
|
||||
requires to be a constant expression.
|
||||
|
@ -3328,6 +3713,27 @@ pointer_int_sum (location_t location, enum tree_code resultcode,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Wrap a SAVE_EXPR around EXPR, if appropriate. Like save_expr, but
|
||||
for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
|
||||
around the SAVE_EXPR if needed so that c_fully_fold does not need
|
||||
to look inside SAVE_EXPRs. */
|
||||
|
||||
tree
|
||||
c_save_expr (tree expr)
|
||||
{
|
||||
bool maybe_const = true;
|
||||
if (c_dialect_cxx ())
|
||||
return save_expr (expr);
|
||||
expr = c_fully_fold (expr, false, &maybe_const);
|
||||
expr = save_expr (expr);
|
||||
if (!maybe_const)
|
||||
{
|
||||
expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
|
||||
C_MAYBE_CONST_EXPR_NON_CONST (expr) = 1;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* Return whether EXPR is a declaration whose address can never be
|
||||
NULL. */
|
||||
|
||||
|
@ -3470,12 +3876,23 @@ c_common_truthvalue_conversion (location_t location, tree expr)
|
|||
|
||||
case COND_EXPR:
|
||||
/* Distribute the conversion into the arms of a COND_EXPR. */
|
||||
return fold_build3 (COND_EXPR, truthvalue_type_node,
|
||||
TREE_OPERAND (expr, 0),
|
||||
c_common_truthvalue_conversion (location,
|
||||
TREE_OPERAND (expr, 1)),
|
||||
c_common_truthvalue_conversion (location,
|
||||
TREE_OPERAND (expr, 2)));
|
||||
if (c_dialect_cxx ())
|
||||
return fold_build3 (COND_EXPR, truthvalue_type_node,
|
||||
TREE_OPERAND (expr, 0),
|
||||
c_common_truthvalue_conversion (location,
|
||||
TREE_OPERAND (expr,
|
||||
1)),
|
||||
c_common_truthvalue_conversion (location,
|
||||
TREE_OPERAND (expr,
|
||||
2)));
|
||||
else
|
||||
/* Folding will happen later for C. */
|
||||
return build3 (COND_EXPR, truthvalue_type_node,
|
||||
TREE_OPERAND (expr, 0),
|
||||
c_common_truthvalue_conversion (location,
|
||||
TREE_OPERAND (expr, 1)),
|
||||
c_common_truthvalue_conversion (location,
|
||||
TREE_OPERAND (expr, 2)));
|
||||
|
||||
CASE_CONVERT:
|
||||
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
|
||||
|
@ -3506,7 +3923,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
|
|||
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
|
||||
{
|
||||
tree t = save_expr (expr);
|
||||
tree t = c_save_expr (expr);
|
||||
return (build_binary_op
|
||||
(EXPR_LOCATION (expr),
|
||||
(TREE_SIDE_EFFECTS (expr)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
additional tree codes used in the GNU C compiler (see tree.def
|
||||
for the standard codes).
|
||||
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>
|
||||
|
||||
This file is part of GCC.
|
||||
|
@ -31,6 +31,21 @@ along with GCC; see the file COPYING3. If not see
|
|||
the compound literal. */
|
||||
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:
|
||||
mode:c
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Definitions for c-common.c.
|
||||
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.
|
||||
|
||||
This file is part of GCC.
|
||||
|
@ -30,8 +30,10 @@ along with GCC; see the file COPYING3. If not see
|
|||
0: TREE_NEGATED_INT (in INTEGER_CST).
|
||||
IDENTIFIER_MARKED (used by search routines).
|
||||
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)
|
||||
STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST)
|
||||
C_MAYBE_CONST_EXPR_NON_CONST (in C_MAYBE_CONST_EXPR, for C)
|
||||
2: unused
|
||||
3: STATEMENT_LIST_HAS_LABEL (in STATEMENT_LIST)
|
||||
4: unused
|
||||
|
@ -715,6 +717,9 @@ extern tree c_common_signed_type (tree);
|
|||
extern tree c_common_signed_or_unsigned_type (int, tree);
|
||||
extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
|
||||
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 void c_apply_type_quals_to_decl (int, tree);
|
||||
extern tree c_sizeof_or_alignof_type (tree, bool, int);
|
||||
|
@ -799,6 +804,21 @@ extern void finish_file (void);
|
|||
#define COMPOUND_LITERAL_EXPR_DECL(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. */
|
||||
#define DECL_C_BIT_FIELD(NODE) \
|
||||
(DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Language-level data type conversion for GNU C.
|
||||
Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008,
|
||||
2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
|
@ -86,6 +86,8 @@ convert (tree type, tree expr)
|
|||
if (type == TREE_TYPE (expr))
|
||||
return expr;
|
||||
|
||||
STRIP_TYPE_NOPS (e);
|
||||
|
||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
|
||||
return fold_convert (type, expr);
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
|
||||
|
|
115
gcc/c-decl.c
115
gcc/c-decl.c
|
@ -410,8 +410,8 @@ static tree lookup_name_in_scope (tree, struct c_scope *);
|
|||
static tree c_make_fname_decl (tree, int);
|
||||
static tree grokdeclarator (const struct c_declarator *,
|
||||
struct c_declspecs *,
|
||||
enum decl_context, bool, tree *, tree *,
|
||||
enum deprecated_states);
|
||||
enum decl_context, bool, tree *, tree *, tree *,
|
||||
bool *, enum deprecated_states);
|
||||
static tree grokparms (struct c_arg_info *, bool);
|
||||
static void layout_array_type (tree);
|
||||
|
||||
|
@ -3128,10 +3128,15 @@ add_flexible_array_elts_to_size (tree decl, tree init)
|
|||
}
|
||||
}
|
||||
|
||||
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
|
||||
/* Decode a "typename", such as "int **", returning a ..._TYPE node.
|
||||
Set *EXPR, if EXPR not NULL, to any expression to be evaluated
|
||||
before the type name, and set *EXPR_CONST_OPERANDS, if
|
||||
EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
|
||||
appear in a constant expression. */
|
||||
|
||||
tree
|
||||
groktypename (struct c_type_name *type_name)
|
||||
groktypename (struct c_type_name *type_name, tree *expr,
|
||||
bool *expr_const_operands)
|
||||
{
|
||||
tree type;
|
||||
tree attrs = type_name->specs->attrs;
|
||||
|
@ -3139,7 +3144,8 @@ groktypename (struct c_type_name *type_name)
|
|||
type_name->specs->attrs = NULL_TREE;
|
||||
|
||||
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
|
||||
false, NULL, &attrs, DEPRECATED_NORMAL);
|
||||
false, NULL, &attrs, expr, expr_const_operands,
|
||||
DEPRECATED_NORMAL);
|
||||
|
||||
/* Apply attributes. */
|
||||
decl_attributes (&type, attrs, 0);
|
||||
|
@ -3168,6 +3174,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
|
|||
{
|
||||
tree decl;
|
||||
tree tem;
|
||||
tree expr = NULL_TREE;
|
||||
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
|
||||
|
||||
/* An object declared as __attribute__((deprecated)) suppresses
|
||||
|
@ -3176,11 +3183,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
|
|||
deprecated_state = DEPRECATED_SUPPRESS;
|
||||
|
||||
decl = grokdeclarator (declarator, declspecs,
|
||||
NORMAL, initialized, NULL, &attributes,
|
||||
NORMAL, initialized, NULL, &attributes, &expr, NULL,
|
||||
deprecated_state);
|
||||
if (!decl)
|
||||
return 0;
|
||||
|
||||
if (expr)
|
||||
add_stmt (expr);
|
||||
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
|
||||
warning (OPT_Wmain, "%q+D is usually a function", decl);
|
||||
|
||||
|
@ -3668,7 +3678,7 @@ grokparm (const struct c_parm *parm)
|
|||
{
|
||||
tree attrs = parm->attrs;
|
||||
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
|
||||
NULL, &attrs, DEPRECATED_NORMAL);
|
||||
NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
|
||||
|
||||
decl_attributes (&decl, attrs, 0);
|
||||
|
||||
|
@ -3685,7 +3695,7 @@ push_parm_decl (const struct c_parm *parm)
|
|||
tree decl;
|
||||
|
||||
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
|
||||
&attrs, DEPRECATED_NORMAL);
|
||||
&attrs, NULL, NULL, DEPRECATED_NORMAL);
|
||||
decl_attributes (&decl, attrs, 0);
|
||||
|
||||
decl = pushdecl (decl);
|
||||
|
@ -3716,10 +3726,11 @@ mark_forward_parm_decls (void)
|
|||
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
|
||||
literal, which may be an incomplete array type completed by the
|
||||
initializer; INIT is a CONSTRUCTOR that initializes the compound
|
||||
literal. */
|
||||
literal. NON_CONST is true if the initializers contain something
|
||||
that cannot occur in a constant expression. */
|
||||
|
||||
tree
|
||||
build_compound_literal (tree type, tree init)
|
||||
build_compound_literal (tree type, tree init, bool non_const)
|
||||
{
|
||||
/* We do not use start_decl here because we have a type, not a declarator;
|
||||
and do not use finish_decl because the decl should be stored inside
|
||||
|
@ -3772,6 +3783,12 @@ build_compound_literal (tree type, tree init)
|
|||
rest_of_decl_compilation (decl, 1, 0);
|
||||
}
|
||||
|
||||
if (non_const)
|
||||
{
|
||||
complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
|
||||
C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
|
||||
}
|
||||
|
||||
return complit;
|
||||
}
|
||||
|
||||
|
@ -3958,6 +3975,11 @@ warn_variable_length_array (const char *name, tree size)
|
|||
DECL_ATTRS points to the list of attributes that should be added to this
|
||||
decl. Any nested attributes that belong on the decl itself will be
|
||||
added to this list.
|
||||
If EXPR is not NULL, any expressions that need to be evaluated as
|
||||
part of evaluating variably modified types will be stored in *EXPR.
|
||||
If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
|
||||
set to indicate whether operands in *EXPR can be used in constant
|
||||
expressions.
|
||||
DEPRECATED_STATE is a deprecated_states value indicating whether
|
||||
deprecation warnings should be suppressed.
|
||||
|
||||
|
@ -3972,7 +3994,8 @@ static tree
|
|||
grokdeclarator (const struct c_declarator *declarator,
|
||||
struct c_declspecs *declspecs,
|
||||
enum decl_context decl_context, bool initialized, tree *width,
|
||||
tree *decl_attrs, enum deprecated_states deprecated_state)
|
||||
tree *decl_attrs, tree *expr, bool *expr_const_operands,
|
||||
enum deprecated_states deprecated_state)
|
||||
{
|
||||
tree type = declspecs->type;
|
||||
bool threadp = declspecs->thread_p;
|
||||
|
@ -3994,6 +4017,16 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
bool bitfield = width != NULL;
|
||||
tree element_type;
|
||||
struct c_arg_info *arg_info = 0;
|
||||
tree expr_dummy;
|
||||
bool expr_const_operands_dummy;
|
||||
|
||||
if (expr == NULL)
|
||||
expr = &expr_dummy;
|
||||
if (expr_const_operands == NULL)
|
||||
expr_const_operands = &expr_const_operands_dummy;
|
||||
|
||||
*expr = declspecs->expr;
|
||||
*expr_const_operands = declspecs->expr_const_operands;
|
||||
|
||||
if (decl_context == FUNCDEF)
|
||||
funcdef_flag = true, decl_context = NORMAL;
|
||||
|
@ -4306,6 +4339,11 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
|
||||
if (size)
|
||||
{
|
||||
bool size_maybe_const = true;
|
||||
bool size_int_const = (TREE_CODE (size) == INTEGER_CST
|
||||
&& !TREE_OVERFLOW (size));
|
||||
bool this_size_varies = false;
|
||||
|
||||
/* Strip NON_LVALUE_EXPRs since we aren't using as an
|
||||
lvalue. */
|
||||
STRIP_TYPE_NOPS (size);
|
||||
|
@ -4316,11 +4354,13 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
size = integer_one_node;
|
||||
}
|
||||
|
||||
if (pedantic && integer_zerop (size))
|
||||
size = c_fully_fold (size, false, &size_maybe_const);
|
||||
|
||||
if (pedantic && size_maybe_const && integer_zerop (size))
|
||||
pedwarn (input_location, OPT_pedantic,
|
||||
"ISO C forbids zero-size array %qs", name);
|
||||
|
||||
if (TREE_CODE (size) == INTEGER_CST)
|
||||
if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
|
||||
{
|
||||
constant_expression_warning (size);
|
||||
if (tree_int_cst_sgn (size) < 0)
|
||||
|
@ -4328,6 +4368,13 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
error ("size of array %qs is negative", name);
|
||||
size = integer_one_node;
|
||||
}
|
||||
/* Handle a size folded to an integer constant but
|
||||
not an integer constant expression. */
|
||||
if (!size_int_const)
|
||||
{
|
||||
this_size_varies = size_varies = 1;
|
||||
warn_variable_length_array (orig_name, size);
|
||||
}
|
||||
}
|
||||
else if ((decl_context == NORMAL || decl_context == FIELD)
|
||||
&& current_scope == file_scope)
|
||||
|
@ -4340,11 +4387,11 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
/* Make sure the array size remains visibly
|
||||
nonconstant even if it is (eg) a const variable
|
||||
with known value. */
|
||||
size_varies = 1;
|
||||
this_size_varies = size_varies = 1;
|
||||
warn_variable_length_array (orig_name, size);
|
||||
}
|
||||
|
||||
if (integer_zerop (size))
|
||||
if (integer_zerop (size) && !this_size_varies)
|
||||
{
|
||||
/* A zero-length array cannot be represented with
|
||||
an unsigned index type, which is what we'll
|
||||
|
@ -4359,6 +4406,9 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
with the +1 that happens when building TYPE_SIZE. */
|
||||
if (size_varies)
|
||||
size = variable_size (size);
|
||||
if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
|
||||
size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
|
||||
integer_zero_node, size);
|
||||
|
||||
/* Compute the maximum valid index, that is, size
|
||||
- 1. Do the calculation in index_type, so that
|
||||
|
@ -4386,6 +4436,15 @@ grokdeclarator (const struct c_declarator *declarator,
|
|||
|
||||
itype = build_index_type (itype);
|
||||
}
|
||||
if (this_size_varies)
|
||||
{
|
||||
if (*expr)
|
||||
*expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
|
||||
*expr, size);
|
||||
else
|
||||
*expr = size;
|
||||
*expr_const_operands &= size_maybe_const;
|
||||
}
|
||||
}
|
||||
else if (decl_context == FIELD)
|
||||
{
|
||||
|
@ -5288,10 +5347,15 @@ struct c_typespec
|
|||
parser_xref_tag (enum tree_code code, tree name)
|
||||
{
|
||||
struct c_typespec ret;
|
||||
tree ref;
|
||||
|
||||
ret.expr = NULL_TREE;
|
||||
ret.expr_const_operands = true;
|
||||
|
||||
/* If a cross reference is requested, look up the type
|
||||
already defined for this tag and return it. */
|
||||
|
||||
tree ref = lookup_tag (code, name, 0);
|
||||
ref = lookup_tag (code, name, 0);
|
||||
/* If this is the right type of tag, return what we found.
|
||||
(This reference will be shadowed by shadow_tag later if appropriate.)
|
||||
If this is the wrong type of tag, do not return it. If it was the
|
||||
|
@ -5460,7 +5524,7 @@ grokfield (location_t loc,
|
|||
}
|
||||
|
||||
value = grokdeclarator (declarator, declspecs, FIELD, false,
|
||||
width ? &width : NULL, decl_attrs,
|
||||
width ? &width : NULL, decl_attrs, NULL, NULL,
|
||||
DEPRECATED_NORMAL);
|
||||
|
||||
finish_decl (value, NULL_TREE, NULL_TREE);
|
||||
|
@ -6119,7 +6183,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
|
|||
c_break_label = c_cont_label = size_zero_node;
|
||||
|
||||
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
|
||||
&attributes, DEPRECATED_NORMAL);
|
||||
&attributes, NULL, NULL, DEPRECATED_NORMAL);
|
||||
|
||||
/* If the declarator is not suitable for a function definition,
|
||||
cause a syntax error. */
|
||||
|
@ -7132,10 +7196,12 @@ build_null_declspecs (void)
|
|||
{
|
||||
struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
|
||||
ret->type = 0;
|
||||
ret->expr = 0;
|
||||
ret->decl_attr = 0;
|
||||
ret->attrs = 0;
|
||||
ret->typespec_word = cts_none;
|
||||
ret->storage_class = csc_none;
|
||||
ret->expr_const_operands = true;
|
||||
ret->declspecs_seen_p = false;
|
||||
ret->type_seen_p = false;
|
||||
ret->non_sc_seen_p = false;
|
||||
|
@ -7657,7 +7723,18 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
|||
if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
|
||||
specs->tag_defined_p = true;
|
||||
if (spec.kind == ctsk_typeof)
|
||||
specs->typedef_p = true;
|
||||
{
|
||||
specs->typedef_p = true;
|
||||
if (spec.expr)
|
||||
{
|
||||
if (specs->expr)
|
||||
specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
|
||||
specs->expr, spec.expr);
|
||||
else
|
||||
specs->expr = spec.expr;
|
||||
specs->expr_const_operands &= spec.expr_const_operands;
|
||||
}
|
||||
}
|
||||
specs->type = type;
|
||||
}
|
||||
|
||||
|
|
149
gcc/c-parser.c
149
gcc/c-parser.c
|
@ -915,7 +915,7 @@ static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
|
|||
struct c_expr);
|
||||
static struct c_expr c_parser_expression (c_parser *);
|
||||
static struct c_expr c_parser_expression_conv (c_parser *);
|
||||
static tree c_parser_expr_list (c_parser *, bool);
|
||||
static tree c_parser_expr_list (c_parser *, bool, bool);
|
||||
static void c_parser_omp_construct (c_parser *);
|
||||
static void c_parser_omp_threadprivate (c_parser *);
|
||||
static void c_parser_omp_barrier (c_parser *);
|
||||
|
@ -1455,6 +1455,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
|||
/* For a typedef name, record the meaning, not the name.
|
||||
In case of 'foo foo, bar;'. */
|
||||
t.spec = lookup_name (value);
|
||||
t.expr = NULL_TREE;
|
||||
t.expr_const_operands = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1464,6 +1466,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
|||
if (c_parser_next_token_is (parser, CPP_LESS))
|
||||
proto = c_parser_objc_protocol_refs (parser);
|
||||
t.spec = objc_get_protocol_qualified_type (value, proto);
|
||||
t.expr = NULL_TREE;
|
||||
t.expr_const_operands = true;
|
||||
}
|
||||
declspecs_add_type (specs, t);
|
||||
continue;
|
||||
|
@ -1479,6 +1483,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
|||
proto = c_parser_objc_protocol_refs (parser);
|
||||
t.kind = ctsk_objc;
|
||||
t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
|
||||
t.expr = NULL_TREE;
|
||||
t.expr_const_operands = true;
|
||||
declspecs_add_type (specs, t);
|
||||
continue;
|
||||
}
|
||||
|
@ -1526,6 +1532,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
|
|||
parser->objc_need_raw_identifier = true;
|
||||
t.kind = ctsk_resword;
|
||||
t.spec = c_parser_peek_token (parser)->value;
|
||||
t.expr = NULL_TREE;
|
||||
t.expr_const_operands = true;
|
||||
declspecs_add_type (specs, t);
|
||||
c_parser_consume_token (parser);
|
||||
break;
|
||||
|
@ -1687,6 +1695,8 @@ c_parser_enum_specifier (c_parser *parser)
|
|||
ret.spec = finish_enum (type, nreverse (values),
|
||||
chainon (attrs, postfix_attrs));
|
||||
ret.kind = ctsk_tagdef;
|
||||
ret.expr = NULL_TREE;
|
||||
ret.expr_const_operands = true;
|
||||
return ret;
|
||||
}
|
||||
else if (!ident)
|
||||
|
@ -1694,6 +1704,8 @@ c_parser_enum_specifier (c_parser *parser)
|
|||
c_parser_error (parser, "expected %<{%>");
|
||||
ret.spec = error_mark_node;
|
||||
ret.kind = ctsk_tagref;
|
||||
ret.expr = NULL_TREE;
|
||||
ret.expr_const_operands = true;
|
||||
return ret;
|
||||
}
|
||||
ret = parser_xref_tag (ENUMERAL_TYPE, ident);
|
||||
|
@ -1870,6 +1882,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
|
|||
ret.spec = finish_struct (type, nreverse (contents),
|
||||
chainon (attrs, postfix_attrs));
|
||||
ret.kind = ctsk_tagdef;
|
||||
ret.expr = NULL_TREE;
|
||||
ret.expr_const_operands = true;
|
||||
return ret;
|
||||
}
|
||||
else if (!ident)
|
||||
|
@ -1877,6 +1891,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
|
|||
c_parser_error (parser, "expected %<{%>");
|
||||
ret.spec = error_mark_node;
|
||||
ret.kind = ctsk_tagref;
|
||||
ret.expr = NULL_TREE;
|
||||
ret.expr_const_operands = true;
|
||||
return ret;
|
||||
}
|
||||
ret = parser_xref_tag (code, ident);
|
||||
|
@ -2053,6 +2069,8 @@ c_parser_typeof_specifier (c_parser *parser)
|
|||
struct c_typespec ret;
|
||||
ret.kind = ctsk_typeof;
|
||||
ret.spec = error_mark_node;
|
||||
ret.expr = NULL_TREE;
|
||||
ret.expr_const_operands = true;
|
||||
gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
|
||||
c_parser_consume_token (parser);
|
||||
skip_evaluation++;
|
||||
|
@ -2070,7 +2088,7 @@ c_parser_typeof_specifier (c_parser *parser)
|
|||
in_typeof--;
|
||||
if (type != NULL)
|
||||
{
|
||||
ret.spec = groktypename (type);
|
||||
ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
|
||||
pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
|
||||
}
|
||||
}
|
||||
|
@ -2086,22 +2104,10 @@ c_parser_typeof_specifier (c_parser *parser)
|
|||
error_at (here, "%<typeof%> applied to a bit-field");
|
||||
ret.spec = TREE_TYPE (expr.value);
|
||||
was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
|
||||
/* This should be returned with the type so that when the type
|
||||
is evaluated, this can be evaluated. For now, we avoid
|
||||
evaluation when the context might. */
|
||||
if (!skip_evaluation && was_vm)
|
||||
{
|
||||
tree e = expr.value;
|
||||
|
||||
/* If the expression is not of a type to which we cannot assign a line
|
||||
number, wrap the thing in a no-op NOP_EXPR. */
|
||||
if (DECL_P (e) || CONSTANT_CLASS_P (e))
|
||||
e = build1 (NOP_EXPR, void_type_node, e);
|
||||
|
||||
protected_set_expr_location (e, here);
|
||||
|
||||
add_stmt (e);
|
||||
}
|
||||
/* This is returned with the type so that when the type is
|
||||
evaluated, this can be evaluated. */
|
||||
if (was_vm)
|
||||
ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
|
||||
pop_maybe_used (was_vm);
|
||||
}
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
||||
|
@ -2858,7 +2864,8 @@ c_parser_attributes (c_parser *parser)
|
|||
{
|
||||
c_parser_consume_token (parser);
|
||||
attr_args = tree_cons (NULL_TREE, arg1,
|
||||
c_parser_expr_list (parser, false));
|
||||
c_parser_expr_list (parser, false,
|
||||
true));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2866,7 +2873,7 @@ c_parser_attributes (c_parser *parser)
|
|||
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
||||
attr_args = NULL_TREE;
|
||||
else
|
||||
attr_args = c_parser_expr_list (parser, false);
|
||||
attr_args = c_parser_expr_list (parser, false, true);
|
||||
}
|
||||
attr = build_tree_list (attr_name, attr_args);
|
||||
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
||||
|
@ -3748,8 +3755,9 @@ c_parser_statement_after_labels (c_parser *parser)
|
|||
}
|
||||
else
|
||||
{
|
||||
stmt
|
||||
= objc_build_throw_stmt (c_parser_expression (parser).value);
|
||||
tree expr = c_parser_expression (parser).value;
|
||||
expr = c_fully_fold (expr, false, NULL);
|
||||
stmt = objc_build_throw_stmt (expr);
|
||||
goto expect_semicolon;
|
||||
}
|
||||
break;
|
||||
|
@ -3810,8 +3818,9 @@ c_parser_condition (c_parser *parser)
|
|||
location_t loc;
|
||||
tree cond;
|
||||
loc = c_parser_peek_token (parser)->location;
|
||||
cond = c_objc_common_truthvalue_conversion
|
||||
(loc, c_parser_expression_conv (parser).value);
|
||||
cond = c_parser_expression_conv (parser).value;
|
||||
cond = c_objc_common_truthvalue_conversion (loc, cond);
|
||||
cond = c_fully_fold (cond, false, NULL);
|
||||
protected_set_expr_location (cond, loc);
|
||||
if (warn_sequence_point)
|
||||
verify_sequence_points (cond);
|
||||
|
@ -4304,6 +4313,7 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
|
|||
expr = c_parser_expression (parser);
|
||||
if (convert_p)
|
||||
expr = default_function_array_conversion (expr);
|
||||
expr.value = c_fully_fold (expr.value, false, NULL);
|
||||
parser->lex_untranslated_string = true;
|
||||
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
|
||||
{
|
||||
|
@ -4458,7 +4468,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
|
|||
pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
|
||||
"ISO C forbids omitting the middle term of a ?: expression");
|
||||
/* Make sure first operand is calculated only once. */
|
||||
exp1.value = save_expr (default_conversion (cond.value));
|
||||
exp1.value = c_save_expr (default_conversion (cond.value));
|
||||
cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
|
||||
skip_evaluation += cond.value == truthvalue_true_node;
|
||||
}
|
||||
|
@ -4482,7 +4492,9 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
|
|||
exp2 = c_parser_conditional_expression (parser, NULL);
|
||||
exp2 = default_function_array_conversion (exp2);
|
||||
skip_evaluation -= cond.value == truthvalue_true_node;
|
||||
ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
|
||||
ret.value = build_conditional_expr (cond.value,
|
||||
cond.original_code == C_MAYBE_CONST_EXPR,
|
||||
exp1.value, exp2.value);
|
||||
ret.original_code = ERROR_MARK;
|
||||
return ret;
|
||||
}
|
||||
|
@ -5012,7 +5024,7 @@ c_parser_alignof_expression (c_parser *parser)
|
|||
/* alignof ( type-name ). */
|
||||
skip_evaluation--;
|
||||
in_alignof--;
|
||||
ret.value = c_alignof (groktypename (type_name));
|
||||
ret.value = c_alignof (groktypename (type_name, NULL, NULL));
|
||||
ret.original_code = ERROR_MARK;
|
||||
return ret;
|
||||
}
|
||||
|
@ -5200,7 +5212,8 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
expr = c_parser_expression (parser);
|
||||
if (TREE_CODE (expr.value) == MODIFY_EXPR)
|
||||
TREE_NO_WARNING (expr.value) = 1;
|
||||
expr.original_code = ERROR_MARK;
|
||||
if (expr.original_code != C_MAYBE_CONST_EXPR)
|
||||
expr.original_code = ERROR_MARK;
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
}
|
||||
|
@ -5226,6 +5239,7 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
break;
|
||||
}
|
||||
e1 = c_parser_expr_no_commas (parser, NULL);
|
||||
e1.value = c_fully_fold (e1.value, false, NULL);
|
||||
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
|
||||
{
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
|
||||
|
@ -5243,7 +5257,17 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
}
|
||||
else
|
||||
{
|
||||
expr.value = build_va_arg (e1.value, groktypename (t1));
|
||||
tree type_expr = NULL_TREE;
|
||||
expr.value = build_va_arg (e1.value, groktypename (t1,
|
||||
&type_expr,
|
||||
NULL));
|
||||
if (type_expr)
|
||||
{
|
||||
expr.value = build2 (C_MAYBE_CONST_EXPR,
|
||||
TREE_TYPE (expr.value), type_expr,
|
||||
expr.value);
|
||||
C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
|
||||
}
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
break;
|
||||
|
@ -5270,7 +5294,7 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
break;
|
||||
}
|
||||
{
|
||||
tree type = groktypename (t1);
|
||||
tree type = groktypename (t1, NULL, NULL);
|
||||
tree offsetof_ref;
|
||||
if (type == error_mark_node)
|
||||
offsetof_ref = error_mark_node;
|
||||
|
@ -5319,6 +5343,7 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
loc = c_parser_peek_token (parser)->location;
|
||||
c_parser_consume_token (parser);
|
||||
idx = c_parser_expression (parser).value;
|
||||
idx = c_fully_fold (idx, false, NULL);
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
|
||||
"expected %<]%>");
|
||||
offsetof_ref = build_array_ref (offsetof_ref, idx, loc);
|
||||
|
@ -5365,10 +5390,12 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
tree c;
|
||||
|
||||
c = fold (e1.value);
|
||||
if (TREE_CODE (c) != INTEGER_CST)
|
||||
if (TREE_CODE (c) != INTEGER_CST
|
||||
|| !INTEGRAL_TYPE_P (TREE_TYPE (c)))
|
||||
error_at (loc,
|
||||
"first argument to %<__builtin_choose_expr%> not"
|
||||
" a constant");
|
||||
constant_expression_warning (c);
|
||||
expr = integer_zerop (c) ? e3 : e2;
|
||||
}
|
||||
break;
|
||||
|
@ -5406,8 +5433,8 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
{
|
||||
tree e1, e2;
|
||||
|
||||
e1 = TYPE_MAIN_VARIANT (groktypename (t1));
|
||||
e2 = TYPE_MAIN_VARIANT (groktypename (t2));
|
||||
e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL));
|
||||
e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL));
|
||||
|
||||
expr.value = comptypes (e1, e2)
|
||||
? build_int_cst (NULL_TREE, 1)
|
||||
|
@ -5479,7 +5506,7 @@ c_parser_postfix_expression (c_parser *parser)
|
|||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
{
|
||||
tree type = groktypename (t1);
|
||||
tree type = groktypename (t1, NULL, NULL);
|
||||
expr.value = objc_build_encode_expr (type);
|
||||
expr.original_code = ERROR_MARK;
|
||||
}
|
||||
|
@ -5529,10 +5556,13 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
|||
{
|
||||
tree type;
|
||||
struct c_expr init;
|
||||
bool non_const;
|
||||
struct c_expr expr;
|
||||
location_t start_loc;
|
||||
tree type_expr = NULL_TREE;
|
||||
bool type_expr_const = true;
|
||||
start_init (NULL_TREE, NULL, 0);
|
||||
type = groktypename (type_name);
|
||||
type = groktypename (type_name, &type_expr, &type_expr_const);
|
||||
start_loc = c_parser_peek_token (parser)->location;
|
||||
if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
|
||||
{
|
||||
|
@ -5545,8 +5575,26 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
|||
|
||||
if (!flag_isoc99)
|
||||
pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
|
||||
expr.value = build_compound_literal (type, init.value);
|
||||
non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
|
||||
? CONSTRUCTOR_NON_CONST (init.value)
|
||||
: init.original_code == C_MAYBE_CONST_EXPR);
|
||||
non_const |= !type_expr_const;
|
||||
expr.value = build_compound_literal (type, init.value, non_const);
|
||||
expr.original_code = ERROR_MARK;
|
||||
if (type_expr)
|
||||
{
|
||||
if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
|
||||
{
|
||||
gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
|
||||
C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (!non_const);
|
||||
expr.value = build2 (C_MAYBE_CONST_EXPR, type,
|
||||
type_expr, expr.value);
|
||||
}
|
||||
}
|
||||
return c_parser_postfix_expression_after_primary (parser, expr);
|
||||
}
|
||||
|
||||
|
@ -5557,6 +5605,7 @@ static struct c_expr
|
|||
c_parser_postfix_expression_after_primary (c_parser *parser,
|
||||
struct c_expr expr)
|
||||
{
|
||||
struct c_expr orig_expr;
|
||||
tree ident, idx, exprlist;
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
while (true)
|
||||
|
@ -5579,11 +5628,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
|
|||
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
||||
exprlist = NULL_TREE;
|
||||
else
|
||||
exprlist = c_parser_expr_list (parser, true);
|
||||
exprlist = c_parser_expr_list (parser, true, false);
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
|
||||
"expected %<)%>");
|
||||
orig_expr = expr;
|
||||
expr.value = build_function_call (expr.value, exprlist);
|
||||
expr.original_code = ERROR_MARK;
|
||||
if (TREE_CODE (expr.value) == INTEGER_CST
|
||||
&& TREE_CODE (orig_expr.value) == FUNCTION_DECL
|
||||
&& DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
|
||||
&& DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
|
||||
expr.original_code = C_MAYBE_CONST_EXPR;
|
||||
break;
|
||||
case CPP_DOT:
|
||||
/* Structure element reference. */
|
||||
|
@ -5681,7 +5736,7 @@ c_parser_expression_conv (c_parser *parser)
|
|||
}
|
||||
|
||||
/* Parse a non-empty list of expressions. If CONVERT_P, convert
|
||||
functions and arrays to pointers.
|
||||
functions and arrays to pointers. If FOLD_P, fold the expressions.
|
||||
|
||||
nonempty-expr-list:
|
||||
assignment-expression
|
||||
|
@ -5689,13 +5744,15 @@ c_parser_expression_conv (c_parser *parser)
|
|||
*/
|
||||
|
||||
static tree
|
||||
c_parser_expr_list (c_parser *parser, bool convert_p)
|
||||
c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p)
|
||||
{
|
||||
struct c_expr expr;
|
||||
tree ret, cur;
|
||||
expr = c_parser_expr_no_commas (parser, NULL);
|
||||
if (convert_p)
|
||||
expr = default_function_array_conversion (expr);
|
||||
if (fold_p)
|
||||
expr.value = c_fully_fold (expr.value, false, NULL);
|
||||
ret = cur = build_tree_list (NULL_TREE, expr.value);
|
||||
while (c_parser_next_token_is (parser, CPP_COMMA))
|
||||
{
|
||||
|
@ -5703,6 +5760,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p)
|
|||
expr = c_parser_expr_no_commas (parser, NULL);
|
||||
if (convert_p)
|
||||
expr = default_function_array_conversion (expr);
|
||||
if (fold_p)
|
||||
expr.value = c_fully_fold (expr.value, false, NULL);
|
||||
cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
|
||||
}
|
||||
return ret;
|
||||
|
@ -6288,7 +6347,7 @@ c_parser_objc_type_name (c_parser *parser)
|
|||
if (c_parser_next_token_starts_typename (parser))
|
||||
type_name = c_parser_type_name (parser);
|
||||
if (type_name)
|
||||
type = groktypename (type_name);
|
||||
type = groktypename (type_name, NULL, NULL);
|
||||
return build_tree_list (quals, type);
|
||||
}
|
||||
|
||||
|
@ -6394,6 +6453,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
|
|||
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||
{
|
||||
expr = c_parser_expression (parser).value;
|
||||
expr = c_fully_fold (expr, false, NULL);
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
||||
}
|
||||
else
|
||||
|
@ -6529,7 +6589,7 @@ c_parser_objc_receiver (c_parser *parser)
|
|||
c_parser_consume_token (parser);
|
||||
return objc_get_class_reference (id);
|
||||
}
|
||||
return c_parser_expression (parser).value;
|
||||
return c_fully_fold (c_parser_expression (parser).value, false, NULL);
|
||||
}
|
||||
|
||||
/* Parse objc-message-args.
|
||||
|
@ -6577,7 +6637,7 @@ c_parser_objc_message_args (c_parser *parser)
|
|||
static tree
|
||||
c_parser_objc_keywordexpr (c_parser *parser)
|
||||
{
|
||||
tree list = c_parser_expr_list (parser, true);
|
||||
tree list = c_parser_expr_list (parser, true, true);
|
||||
if (TREE_CHAIN (list) == NULL_TREE)
|
||||
{
|
||||
/* Just return the expression, remove a level of
|
||||
|
@ -7053,6 +7113,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list)
|
|||
{
|
||||
location_t expr_loc = c_parser_peek_token (parser)->location;
|
||||
tree c, t = c_parser_expression (parser).value;
|
||||
t = c_fully_fold (t, false, NULL);
|
||||
|
||||
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
||||
|
||||
|
@ -7231,6 +7292,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
|
|||
|
||||
here = c_parser_peek_token (parser)->location;
|
||||
t = c_parser_expr_no_commas (parser, NULL).value;
|
||||
t = c_fully_fold (t, false, NULL);
|
||||
|
||||
if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
|
||||
error_at (here, "schedule %<runtime%> does not take "
|
||||
|
@ -7430,6 +7492,7 @@ c_parser_omp_atomic (c_parser *parser)
|
|||
c_parser_skip_to_pragma_eol (parser);
|
||||
|
||||
lhs = c_parser_unary_expression (parser).value;
|
||||
lhs = c_fully_fold (lhs, false, NULL);
|
||||
switch (TREE_CODE (lhs))
|
||||
{
|
||||
case ERROR_MARK:
|
||||
|
@ -7491,6 +7554,7 @@ c_parser_omp_atomic (c_parser *parser)
|
|||
rhs_expr = c_parser_expression (parser);
|
||||
rhs_expr = default_function_array_conversion (rhs_expr);
|
||||
rhs = rhs_expr.value;
|
||||
rhs = c_fully_fold (rhs, false, NULL);
|
||||
break;
|
||||
}
|
||||
stmt = c_finish_omp_atomic (code, lhs, rhs);
|
||||
|
@ -7654,6 +7718,7 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
|
|||
|
||||
cond = cond_expr.value;
|
||||
cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
|
||||
cond = c_fully_fold (cond, false, NULL);
|
||||
switch (cond_expr.original_code)
|
||||
{
|
||||
case GT_EXPR:
|
||||
|
|
33
gcc/c-tree.h
33
gcc/c-tree.h
|
@ -146,6 +146,10 @@ struct lang_type GTY(())
|
|||
without prototypes. */
|
||||
#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
|
||||
for code generation alongside a tree representing its value. */
|
||||
struct c_expr
|
||||
|
@ -154,7 +158,9 @@ struct c_expr
|
|||
tree value;
|
||||
/* Record the original unary/binary operator of an expression, which may
|
||||
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). */
|
||||
enum tree_code original_code;
|
||||
};
|
||||
|
@ -190,6 +196,18 @@ struct c_typespec {
|
|||
enum c_typespec_kind kind;
|
||||
/* The specifier itself. */
|
||||
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. */
|
||||
|
@ -227,6 +245,9 @@ struct c_declspecs {
|
|||
whole type, or NULL_TREE if none or a keyword such as "void" or
|
||||
"char" is used. Does not include qualifiers. */
|
||||
tree type;
|
||||
/* Any expression to be evaluated before the type, from a typeof
|
||||
specifier. */
|
||||
tree expr;
|
||||
/* The attributes from a typedef decl. */
|
||||
tree decl_attr;
|
||||
/* When parsing, the attributes. Outside the parser, this will be
|
||||
|
@ -238,6 +259,9 @@ struct c_declspecs {
|
|||
enum c_typespec_keyword typespec_word;
|
||||
/* The storage class specifier, or csc_none if none. */
|
||||
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. */
|
||||
BOOL_BITFIELD declspecs_seen_p : 1;
|
||||
/* Whether a type specifier has been seen. */
|
||||
|
@ -478,7 +502,7 @@ extern tree finish_struct (tree, tree, tree);
|
|||
extern struct c_arg_info *get_parm_info (bool);
|
||||
extern tree grokfield (location_t, struct c_declarator *,
|
||||
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 implicitly_declare (tree);
|
||||
extern void keep_next_level (void);
|
||||
|
@ -532,6 +556,7 @@ extern bool c_vla_unspec_p (tree x, tree fn);
|
|||
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
|
||||
|
||||
/* in c-typeck.c */
|
||||
extern bool in_late_binary_op;
|
||||
extern int in_alignof;
|
||||
extern int in_sizeof;
|
||||
extern int in_typeof;
|
||||
|
@ -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,
|
||||
enum tree_code, 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 c_cast_expr (struct c_type_name *, tree);
|
||||
extern tree build_c_cast (tree, tree);
|
||||
|
@ -577,7 +602,7 @@ extern struct c_expr pop_init_level (int);
|
|||
extern void set_init_index (tree, tree);
|
||||
extern void set_init_label (tree);
|
||||
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 void c_finish_case (tree);
|
||||
extern tree build_asm_expr (tree, tree, tree, tree, bool);
|
||||
|
|
644
gcc/c-typeck.c
644
gcc/c-typeck.c
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
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
|
||||
statements-within-expressions feature. Here is how the two together can
|
||||
be used to define a safe ``maximum'' macro that operates on any
|
||||
|
@ -6635,9 +6639,8 @@ depending on the arguments' types. For example:
|
|||
|
||||
You can use the built-in function @code{__builtin_choose_expr} to
|
||||
evaluate code depending on the value of a constant expression. This
|
||||
built-in function returns @var{exp1} if @var{const_exp}, which is a
|
||||
constant expression that must be able to be determined at compile time,
|
||||
is nonzero. Otherwise it returns 0.
|
||||
built-in function returns @var{exp1} if @var{const_exp}, which is an
|
||||
integer constant expression, is nonzero. Otherwise it returns 0.
|
||||
|
||||
This built-in function is analogous to the @samp{? :} operator in C,
|
||||
except that the expression returned has its type unaltered by promotion
|
||||
|
@ -6716,7 +6719,11 @@ static const int table[] = @{
|
|||
|
||||
@noindent
|
||||
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
|
||||
optimization.
|
||||
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
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>
|
||||
|
||||
PR bootstrap/38262
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Implement classes and message passing for Objective C.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
Contributed by Steve Naroff.
|
||||
|
||||
This file is part of GCC.
|
||||
|
@ -3885,12 +3885,15 @@ objc_finish_try_stmt (void)
|
|||
/* If we're doing Darwin setjmp exceptions, build the big nasty. */
|
||||
if (flag_objc_sjlj_exceptions)
|
||||
{
|
||||
bool save = in_late_binary_op;
|
||||
in_late_binary_op = true;
|
||||
if (!cur_try_context->finally_body)
|
||||
{
|
||||
cur_try_context->finally_locus = input_location;
|
||||
cur_try_context->end_finally_locus = input_location;
|
||||
}
|
||||
stmt = next_sjlj_build_try_catch_finally ();
|
||||
in_late_binary_op = save;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,3 +1,40 @@
|
|||
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>
|
||||
|
||||
* gcc.dg/tree-ssa/forwprop-11.c: New testcase.
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/* 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) ();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/* Test boolean conversion as part of returning unsigned value does
|
||||
not lead to an ICE. */
|
||||
|
||||
_Bool f(unsigned a) { return a & 1; }
|
|
@ -0,0 +1,4 @@
|
|||
/* Test boolean conversion of an overflowing integer return value does
|
||||
not lead to an ICE. */
|
||||
|
||||
_Bool f(void) { return __INT_MAX__ + 1; }
|
|
@ -0,0 +1,27 @@
|
|||
/* 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())
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
/* 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())
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
/* 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
|
|||
foo (void)
|
||||
{
|
||||
int i;
|
||||
static int j = (1 ? 0 : (i = 2)); /* { dg-error "initial" "assignment" { xfail *-*-* } } */
|
||||
static int k = (1 ? 0 : ++i); /* { dg-error "initial" "increment" { xfail *-*-* } } */
|
||||
static int l = (1 ? 0 : --i); /* { dg-error "initial" "decrement" { xfail *-*-* } } */
|
||||
static int m = (1 ? 0 : bar ()); /* { dg-error "initial" "function call" { xfail *-*-* } } */
|
||||
static int n = (1 ? 0 : (2, 3)); /* { dg-error "initial" "comma" { xfail *-*-* } } */
|
||||
static int j = (1 ? 0 : (i = 2)); /* { dg-error "initial" "assignment" } */
|
||||
static int k = (1 ? 0 : ++i); /* { dg-error "initial" "increment" } */
|
||||
static int l = (1 ? 0 : --i); /* { dg-error "initial" "decrement" } */
|
||||
static int m = (1 ? 0 : bar ()); /* { dg-error "initial" "function call" } */
|
||||
static int n = (1 ? 0 : (2, 3)); /* { dg-error "initial" "comma" } */
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* 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" } */
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* 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)
|
|||
{
|
||||
ASSERT_NPC (0);
|
||||
ASSERT_NPC ((void *)0);
|
||||
ASSERT_NOT_NPC ((void *)(void *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */
|
||||
ASSERT_NOT_NPC ((void *)(char *)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" } */
|
||||
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. */
|
||||
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)
|
|||
ASSERT_NPC (0);
|
||||
ASSERT_NOT_NPC (ZERO);
|
||||
ASSERT_NPC (0 + 0);
|
||||
ASSERT_NOT_NPC (ZERO + 0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */
|
||||
ASSERT_NOT_NPC (ZERO + ZERO); /* { 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" } */
|
||||
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_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_NOT_NPC ((char) ZERO);
|
||||
ASSERT_NPC ((int) 0);
|
||||
ASSERT_NOT_NPC ((int) ZERO);
|
||||
ASSERT_NPC ((int) 0.0);
|
||||
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+0.0)); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */
|
||||
ASSERT_NOT_NPC ((int) (double)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" } */
|
||||
ASSERT_NOT_NPC ((int) (double)0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* 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" } */
|
||||
;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* 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 } */
|
|
@ -0,0 +1,27 @@
|
|||
/* 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. */
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/* 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])
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/* 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" } */
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* 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;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* 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" } */
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/* 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)
|
|||
{
|
||||
ASSERT_NPC (0);
|
||||
ASSERT_NPC ((void *)0);
|
||||
ASSERT_NOT_NPC ((void *)(void *)0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */
|
||||
ASSERT_NOT_NPC ((void *)(char *)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" } */
|
||||
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. */
|
||||
ASSERT_NPC ((void *)(1 ? 0 : (0, 0)));
|
||||
}
|
||||
|
|
|
@ -27,19 +27,19 @@ foo (void)
|
|||
ASSERT_NPC (0);
|
||||
ASSERT_NOT_NPC (ZERO);
|
||||
ASSERT_NPC (0 + 0);
|
||||
ASSERT_NOT_NPC (ZERO + 0); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */
|
||||
ASSERT_NOT_NPC (ZERO + ZERO); /* { 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" } */
|
||||
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_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_NOT_NPC ((char) ZERO);
|
||||
ASSERT_NPC ((int) 0);
|
||||
ASSERT_NOT_NPC ((int) ZERO);
|
||||
ASSERT_NPC ((int) 0.0);
|
||||
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+0.0)); /* { dg-bogus "incompatible" "bogus null pointer constant" { xfail *-*-* } } */
|
||||
ASSERT_NOT_NPC ((int) (double)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" } */
|
||||
ASSERT_NOT_NPC ((int) (double)0.0); /* { dg-bogus "incompatible" "bogus null pointer constant" } */
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* 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" } */
|
||||
;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* 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 } */
|
|
@ -0,0 +1,27 @@
|
|||
/* 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. */
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/* 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);
|
|||
void g4(void) { sizeof(int (*)[f4()]); }
|
||||
|
||||
/* 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]); }
|
||||
|
||||
/* OK (non-constant sizeof inside constant sizeof). */
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/* 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));
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* 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" } */
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* 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 } */
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* 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; }));
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* 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 } */
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* 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 {
|
|||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
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" } */
|
||||
/* Again, overflow in evaluated subexpression. */
|
||||
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
|
||||
|
@ -28,6 +28,7 @@ enum e {
|
|||
struct s {
|
||||
int a;
|
||||
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" } */
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
subexpression, so is a null pointer constant. */
|
||||
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" } */
|
||||
/* { 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
|
||||
|
@ -57,6 +59,7 @@ g (int i)
|
|||
switch (i)
|
||||
{
|
||||
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" } */
|
||||
;
|
||||
|
|
|
@ -17,7 +17,7 @@ enum e {
|
|||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
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" } */
|
||||
/* Again, overflow in evaluated subexpression. */
|
||||
E6 = 0 * (INT_MAX + 1), /* { dg-warning "integer overflow in expression" } */
|
||||
|
@ -28,6 +28,7 @@ enum e {
|
|||
struct s {
|
||||
int a;
|
||||
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" } */
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
subexpression, so is a null pointer constant. */
|
||||
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" } */
|
||||
/* { 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
|
||||
|
@ -57,6 +59,7 @@ g (int i)
|
|||
switch (i)
|
||||
{
|
||||
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" } */
|
||||
;
|
||||
|
@ -82,23 +85,23 @@ void
|
|||
h2 (void)
|
||||
{
|
||||
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" } */
|
||||
/* { 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);
|
||||
/* { 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" } */
|
||||
/* { 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);
|
||||
/* { 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" } */
|
||||
/* { 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);
|
||||
/* { 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" } */
|
||||
/* { 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" } */
|
||||
/* { 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);
|
||||
|
@ -122,11 +125,11 @@ h2i (int x)
|
|||
fsi (UINT_MAX); /* { dg-warning "passing argument 1 of 'fsi' as signed due to prototype" } */
|
||||
si = UINT_MAX;
|
||||
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 = x ? -1 : 1U;
|
||||
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 = x ? INT_MIN : 1U;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ enum e {
|
|||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
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" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
|
||||
/* Again, overflow in evaluated subexpression. */
|
||||
|
@ -30,8 +30,9 @@ enum e {
|
|||
struct s {
|
||||
int a;
|
||||
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" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 33 } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 34 } */
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -45,16 +46,17 @@ f (void)
|
|||
|
||||
/* But this expression does need to be constant. */
|
||||
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
|
||||
constants. The third has the overflow in an unevaluated
|
||||
subexpression, so is a null pointer constant. */
|
||||
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 53 } */
|
||||
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 53 } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 54 } */
|
||||
/* { dg-warning "initialization makes pointer from integer without a cast" "null" { target *-*-* } 54 } */
|
||||
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
|
||||
|
@ -63,9 +65,10 @@ g (int i)
|
|||
switch (i)
|
||||
{
|
||||
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" } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 67 } */
|
||||
/* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 70 } */
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ enum e {
|
|||
/* But as in DR#031, the 1/0 in an evaluated subexpression means the
|
||||
whole expression violates the constraints. */
|
||||
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" } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
|
||||
/* Again, overflow in evaluated subexpression. */
|
||||
|
@ -30,8 +30,9 @@ enum e {
|
|||
struct s {
|
||||
int a;
|
||||
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" } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 33 } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 34 } */
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -45,16 +46,17 @@ f (void)
|
|||
|
||||
/* But this expression does need to be constant. */
|
||||
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
|
||||
constants. The third has the overflow in an unevaluated
|
||||
subexpression, so is a null pointer constant. */
|
||||
void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 53 } */
|
||||
/* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } 53 } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 54 } */
|
||||
/* { dg-error "initialization makes pointer from integer without a cast" "null" { target *-*-* } 54 } */
|
||||
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
|
||||
|
@ -63,9 +65,10 @@ g (int i)
|
|||
switch (i)
|
||||
{
|
||||
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" } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 67 } */
|
||||
/* { dg-error "overflow in constant expression" "constant" { target *-*-* } 70 } */
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
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 ("");
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ struct S
|
|||
int b;
|
||||
};
|
||||
|
||||
char c[(char *) &((struct S *) 0)->b - (char *) 0];
|
||||
char d[(__SIZE_TYPE__) &((struct S *) 8)->b];
|
||||
char e[sizeof (c) == __builtin_offsetof (struct S, b) ? 1 : -1];
|
||||
char f[sizeof (d) == __builtin_offsetof (struct S, b) + 8 ? 1 : -1];
|
||||
char c[(char *) &((struct S *) 0)->b - (char *) 0]; /* { dg-error "variable-size" } */
|
||||
char d[(__SIZE_TYPE__) &((struct S *) 8)->b]; /* { dg-error "variable-size" } */
|
||||
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]; /* { dg-error "variably modified" } */
|
||||
|
||||
extern void bar (char *, char *);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* PR middle-end/21781. */
|
||||
/* { 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)
|
|||
int 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" } } */
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* 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);
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* 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);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* 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);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* 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);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* 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);
|
||||
}
|
Loading…
Reference in New Issue