diff options
Diffstat (limited to 'gcc/c')
| -rw-r--r-- | gcc/c/ChangeLog | 23 | ||||
| -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 | 40 | 
5 files changed, 79 insertions, 23 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 3c37ba0..23cc53a 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,26 @@ +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 +	type is void, assign size one as the element_size. +  2025-10-27  H.J. Lu  <hjl.tools@gmail.com>  	PR c/122427 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 371583b..2cef463 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -3179,7 +3179,10 @@ build_access_with_size_for_counted_by (location_t loc, tree ref,    tree result_type = is_fam ? c_build_pointer_type (TREE_TYPE (ref))  		     : TREE_TYPE (ref); -  tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref))); +  tree element_type = TREE_TYPE (TREE_TYPE (ref)); +  tree element_size = VOID_TYPE_P (element_type) +		      ? build_one_cst (size_type_node) +		      : TYPE_SIZE_UNIT (element_type);    tree first_param = is_fam  		     ? c_fully_fold (array_to_pointer_conversion (loc, ref), @@ -12731,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"); @@ -18432,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; @@ -18456,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.  | 
