raven-rhel6/gcc44/gcc44-rh1087806-2.patch
2024-02-21 20:14:44 +06:00

169 lines
5.5 KiB
Diff

2014-08-08 Jason Merrill <jason@redhat.com>
* call.c (build_x_va_arg): Support passing non-POD through ....
(convert_arg_to_ellipsis): Likewise.
* g++.dg/ext/varargs1.C: New test.
* g++.old-deja/g++.other/vaarg3.C: Adjust dg-warning.
* g++.old-deja/g++.brendan/crash63.C: Remove dg-warning.
* g++.dg/warn/var-args1.C: Change dg-warning to dg-error.
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -194,7 +194,6 @@ static conversion *direct_reference_binding (tree, conversion *);
static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
-static tree call_builtin_trap (void);
static tree prep_operand (tree);
static void add_candidates (tree, tree, tree, bool, tree, tree,
int, struct z_candidate **);
@@ -4909,18 +4908,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
return expr;
}
-/* Build a call to __builtin_trap. */
-
-static tree
-call_builtin_trap (void)
-{
- tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
-
- gcc_assert (fn != NULL);
- fn = build_call_n (fn, 0);
- return fn;
-}
-
/* ARG is being passed to a varargs function. Perform any conversions
required. Return the converted value. */
@@ -4958,11 +4945,9 @@ convert_arg_to_ellipsis (tree arg)
there is no need to emit a warning, since the expression won't be
evaluated. We keep the builtin_trap just as a safety check. */
if (!skip_evaluation)
- warning (0, "cannot pass objects of non-POD type %q#T through %<...%>; "
- "call will abort at runtime", TREE_TYPE (arg));
- arg = call_builtin_trap ();
- arg = build2 (COMPOUND_EXPR, integer_type_node, arg,
- integer_zero_node);
+ warning (0, "cannot pass objects of non-POD type %q#T through %<...%>",
+ TREE_TYPE (arg));
+ arg = cp_build_unary_op (ADDR_EXPR, arg, true, tf_warning_or_error);
}
return arg;
@@ -4983,19 +4968,20 @@ build_x_va_arg (tree expr, tree type)
expr = mark_lvalue_use (expr);
- if (TREE_ADDRESSABLE (type)
- || TREE_CODE (type) == REFERENCE_TYPE)
+ if (TREE_CODE (type) == REFERENCE_TYPE)
{
- /* Remove reference types so we don't ICE later on. */
- tree type1 = non_reference (type);
+ error ("cannot receive reference type %qT through %<...%>", type);
+ return error_mark_node;
+ }
+
+ if (TREE_ADDRESSABLE (type))
+ {
+ tree ptr = build_pointer_type (type);
/* Undefined behavior [expr.call] 5.2.2/7. */
- warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
- "call will abort at runtime", type);
- expr = convert (build_pointer_type (type1), null_node);
- expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
- call_builtin_trap (), expr);
- expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
- return expr;
+ warning (0, "cannot receive objects of non-POD type %q#T through %<...%>",
+ type);
+ ptr = build_va_arg (expr, ptr);
+ return cp_build_indirect_ref (ptr, NULL, tf_warning_or_error);
}
return build_va_arg (expr, type);
--- gcc/testsuite/g++.dg/ext/varargs1.C
+++ gcc/testsuite/g++.dg/ext/varargs1.C
@@ -0,0 +1,31 @@
+#include <stdarg.h>
+extern "C" void abort();
+
+void *as[5];
+int i;
+
+struct A {
+ A() { as[i++] = this; }
+ A(const A& a) {
+ if (&a != as[i-1])
+ abort();
+ as[i++] = this;
+ }
+ ~A() {
+ if (this != as[--i])
+ abort();
+ }
+};
+
+void f(int i, ...) {
+ va_list ap;
+ va_start (ap, i);
+ A ar = va_arg (ap, A); // { dg-warning "non-POD" }
+}
+
+int main()
+{
+ f(42,A()); // { dg-warning "non-POD" }
+ if (i != 0)
+ abort();
+}
--- gcc/testsuite/g++.dg/warn/var-args1.C
+++ gcc/testsuite/g++.dg/warn/var-args1.C
@@ -6,6 +6,6 @@ void foo(int, ...)
{
va_list va;
int i;
- i = va_arg(va, int&); /* { dg-warning "cannot receive objects" } */
+ i = va_arg(va, int&); /* { dg-error "cannot receive" } */
}
--- gcc/testsuite/g++.old-deja/g++.brendan/crash63.C
+++ gcc/testsuite/g++.old-deja/g++.brendan/crash63.C
@@ -12,4 +12,4 @@ class UnitList
UnitList (...);
};
-UnitList unit_list (String("keV")); // { dg-warning "" } cannot pass non-pod
+UnitList unit_list (String("keV"));
--- gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
+++ gcc/testsuite/g++.old-deja/g++.other/vaarg3.C
@@ -9,14 +9,14 @@
#include <stdarg.h>
struct X {int m;};
-struct Y : X {int m;};
+struct Y { Y(const Y&); };
struct Z; // { dg-error "forward decl" }
void fn1(va_list args)
{
int i = va_arg (args, int);
Y x = va_arg (args, Y); // { dg-warning "cannot receive" }
Y y = va_arg (args, struct Y); // { dg-warning "cannot receive" }
- int &r = va_arg (args, int &); // { dg-warning "cannot receive" }
+ int &r = va_arg (args, int &); // { dg-error "cannot receive" }
Z z1 = va_arg (args, Z); // { dg-error "incomplete" }
const Z &z2 = va_arg (args, Z); // { dg-error "incomplete" }
@@ -25,7 +25,8 @@ void fn1(va_list args)
// { dg-message "should pass" "pass" { target *-*-* } 24 }
// { dg-message "abort" "abort" { target *-*-* } 24 }
va_arg (args, int []); // { dg-error "array with unspecified bounds" } promote
- va_arg (args, int ()); // { dg-warning "non-POD" } promote
+ va_arg (args, int ()); // { dg-warning "promote" } promote
+ // { dg-message "abort" "abort" { target *-*-* } 28 }
va_arg (args, bool); // { dg-warning "promote" "promote" }
- // { dg-message "abort" "abort" { target *-*-* } 29 }
+ // { dg-message "abort" "abort" { target *-*-* } 30 }
}