diff options
Diffstat (limited to 'gcc/c')
| -rw-r--r-- | gcc/c/ChangeLog | 18 | ||||
| -rw-r--r-- | gcc/c/c-decl.cc | 4 | ||||
| -rw-r--r-- | gcc/c/c-parser.cc | 33 | ||||
| -rw-r--r-- | gcc/c/c-tree.h | 2 | ||||
| -rw-r--r-- | gcc/c/c-typeck.cc | 35 |
5 files changed, 70 insertions, 22 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 274e2a7..23cc53a 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,21 @@ +2025-11-01 Martin Uecker <uecker@tugraz.at> + + * c-decl.cc (build_compound_literal): Add error. + * c-parser.cc (c_parser_braced_init): Take bool argument for + variable size instead of DECL. + (c_parser_initializer,c_parser_initval): Adapt. + (c_parser_postfix_expression_after_paren_type): Change + error to pedwarn. + * c-typeck.cc (process_init_element): Add error for + variable-size compound literal with static or constexpr. + +2025-11-01 Martin Uecker <uecker@tugraz.at> + + PR c/97986 + * c-parser.cc (c_parser_postfix_expression): Adapt. + * c-tree.h (c_build_va_arg): Adapt prototype. + * c-typeck.cc (c_build_va_arg): Handle UB. + 2025-10-30 Qing Zhao <qing.zhao@oracle.com> * c-typeck.cc (build_access_with_size_for_counted_by): When the element diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 2b31a43..1e1da2d 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -6536,6 +6536,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const, return error_mark_node; } + if ((TREE_STATIC (decl) || C_DECL_DECLARED_CONSTEXPR (decl)) + && C_TYPE_VARIABLE_SIZE (type)) + error_at (loc, "storage size isn%'t constant"); + if (TREE_STATIC (decl) && !verify_type_context (loc, TCTX_STATIC_STORAGE, type)) return error_mark_node; diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 0cf3f92..9b3a786 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1767,7 +1767,7 @@ static tree c_parser_simple_asm_expr (c_parser *); static tree c_parser_gnu_attributes (c_parser *); static struct c_expr c_parser_initializer (c_parser *, tree); static struct c_expr c_parser_braced_init (c_parser *, tree, bool, - struct obstack *, tree); + struct obstack *, bool); static void c_parser_initelt (c_parser *, struct obstack *); static void c_parser_initval (c_parser *, struct c_expr *, struct obstack *); @@ -6459,7 +6459,9 @@ static struct c_expr c_parser_initializer (c_parser *parser, tree decl) { if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl); + return c_parser_braced_init (parser, NULL_TREE, false, NULL, + decl != error_mark_node + && C_DECL_VARIABLE_SIZE (decl)); else { struct c_expr ret; @@ -6499,12 +6501,12 @@ location_t last_init_list_comma; compound literal, and NULL_TREE for other initializers and for nested braced lists. NESTED_P is true for nested braced lists, false for the list of a compound literal or the list that is the - top-level initializer in a declaration. DECL is the declaration for - the top-level initializer for a declaration, otherwise NULL_TREE. */ + top-level initializer in a declaration. VARSIZE_P indicates + wether the object to be initialized has a variable size. */ static struct c_expr c_parser_braced_init (c_parser *parser, tree type, bool nested_p, - struct obstack *outer_obstack, tree decl) + struct obstack *outer_obstack, bool varsize_p) { struct c_expr ret; struct obstack braced_init_obstack; @@ -6532,7 +6534,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, } else { - if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) + if (varsize_p) error_at (brace_loc, "variable-sized object may not be initialized except " "with an empty initializer"); @@ -6826,7 +6828,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) init = c_parser_braced_init (parser, NULL_TREE, true, - braced_init_obstack, NULL_TREE); + braced_init_obstack, false); else { init = c_parser_expr_no_commas (parser, after); @@ -11793,15 +11795,9 @@ c_parser_postfix_expression (c_parser *parser) else { tree type_expr = NULL_TREE; + tree type = groktypename (t1, &type_expr, NULL); expr.value = c_build_va_arg (start_loc, e1.value, loc, - 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; - } + type, type_expr); set_c_expr_source_range (&expr, start_loc, end_loc); } } @@ -13516,10 +13512,11 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, || (scspecs && scspecs->storage_class == csc_static) || constexpr_p), constexpr_p, &richloc); type = groktypename (type_name, &type_expr, &type_expr_const); + bool varsize_p = false; if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) { - error_at (type_loc, "compound literal has variable size"); - type = error_mark_node; + pedwarn (type_loc, OPT_Wpedantic, "compound literal has variable size"); + varsize_p = true; } else if (TREE_CODE (type) == FUNCTION_TYPE) { @@ -13544,7 +13541,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, (TYPE_QUALS (type_no_array) | TYPE_QUAL_CONST)); } - init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE); + init = c_parser_braced_init (parser, type, false, NULL, varsize_p); if (constexpr_p) finish_underspecified_init (NULL_TREE, underspec_state); finish_init (); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index f367cda..ff63d69 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -917,7 +917,7 @@ extern tree c_omp_finish_mapper_clauses (tree); extern tree c_omp_mapper_lookup (tree, tree); extern tree c_omp_extract_mapper_directive (tree); extern tree c_omp_map_array_section (location_t, tree); -extern tree c_build_va_arg (location_t, tree, location_t, tree); +extern tree c_build_va_arg (location_t, tree, location_t, tree, tree); extern tree c_finish_transaction (location_t, tree, int); extern bool c_tree_equal (tree, tree); extern tree c_build_function_call_vec (location_t, const vec<location_t>&, diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index bc0fb6b..2cef463 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -12734,7 +12734,9 @@ retry: if (constructor_max_index != NULL_TREE && (tree_int_cst_lt (constructor_max_index, constructor_index) - || integer_all_onesp (constructor_max_index))) + || integer_all_onesp (constructor_max_index)) + /* For VLA we got an error already. */ + && !C_TYPE_VARIABLE_SIZE (constructor_type)) { pedwarn_init (loc, 0, "excess elements in array initializer"); @@ -18435,7 +18437,8 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, /* Build a VA_ARG_EXPR for the C parser. */ tree -c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type) +c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type, + tree type_expr) { if (error_operand_p (type)) return error_mark_node; @@ -18459,10 +18462,36 @@ c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type) type); return error_mark_node; } + else if (TREE_CODE (type) == ARRAY_TYPE && C_TYPE_VARIABLE_SIZE (type) + && !flag_isoc99) + { + error_at (loc2, "second argument to %<va_arg%> is an array type %qT", + type); + return error_mark_node; + } else if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE) warning_at (loc2, OPT_Wc___compat, "C++ requires promoted type, not enum type, in %<va_arg%>"); - return build_va_arg (loc2, expr, type); + + if (flag_isoc99 && TREE_CODE (type) == ARRAY_TYPE) + { + warning_at (loc2, 0, "second argument to %<va_arg%> is an array type %qT", + type); + /* We create a trap but evaluate side effects first. */ + tree trapfn = builtin_decl_explicit (BUILT_IN_TRAP); + trapfn = build_call_expr_loc (loc2, trapfn, 0); + tree e2 = build2 (COMPOUND_EXPR, void_type_node, expr, trapfn); + /* Return a compound literal of the right type. */ + tree e1 = build_compound_literal (loc2, type, NULL, true, 0, NULL); + expr = build2 (COMPOUND_EXPR, type, e2, e1); + } + else + expr = build_va_arg (loc2, expr, type); + + if (type_expr) + expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), type_expr, expr); + + return expr; } /* Return truthvalue of whether T1 is the same tree structure as T2. |
