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);
}
}
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>&,
/* 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;
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.
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-std=gnu23" } */
+
+#include <stdarg.h>
+
+int f(int n, ...)
+{
+ __label__ b, d;
+ va_list ap;
+ va_start(ap, n);
+ _Static_assert(5 == sizeof(va_arg(ap, char[5]))); /* { dg-warning "array type" } */
+ void g(void) { n++; goto b; }
+ int *a = va_arg((g(), ap), int[n]); /* { dg-warning "array type" } */
+b:
+ void h(void) { n++; goto d; }
+ typeof(va_arg(ap, int[(h(), n)])) c; /* { dg-warning "array type" } */
+d:
+ return n;
+}
+
+int main()
+{
+ if (9 != f(7))
+ __builtin_abort();
+ return 0;
+}
+