Revert empty class parameter passing ABI changes.

From-SVN: r234977
This commit is contained in:
Jason Merrill 2016-04-14 12:23:06 -04:00 committed by Jason Merrill
parent 52fbb073e9
commit 9f285ccb77
63 changed files with 49 additions and 1010 deletions

View File

@ -1,3 +1,7 @@
2016-04-14 Jason Merrill <jason@redhat.com>
* cfgexpand.c, expr.c: Revert previous change.
2016-04-14 Cesar Philippidis <cesar@codesourcery.com>
PR middle-end/70643

View File

@ -73,7 +73,6 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "tree-chkp.h"
#include "rtl-chkp.h"
#include "langhooks.h"
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
@ -6222,15 +6221,6 @@ pass_expand::execute (function *fun)
(int) PARAM_VALUE (PARAM_SSP_BUFFER_SIZE));
}
if (warn_abi)
if (tree attr = lookup_attribute ("abi warning",
DECL_ATTRIBUTES (current_function_decl)))
warning_at (DECL_SOURCE_LOCATION (current_function_decl),
OPT_Wabi, "definition of %qs: %s",
identifier_to_locale (lang_hooks.decl_printable_name
(current_function_decl, 1)),
TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
/* Set up parameters and prepare for return, for the function. */
expand_function_start (current_function_decl);

View File

@ -1,3 +1,8 @@
2016-04-14 Jason Merrill <jason@redhat.com>
* call.c, decl.c, error.c, cp-tree.h, decl.c: Revert empty
parameter ABI change.
2016-04-13 Martin Sebor <msebor@redhat.com>
PR c++/69517

View File

@ -214,8 +214,6 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
tsubst_flags_t);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
static bool pass_as_empty_struct (tree type);
static tree empty_class_arg (tree);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
NAME can take many forms... */
@ -381,31 +379,16 @@ build_call_a (tree function, int n, tree *argarray)
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */
bool warned = false;
if (decl && !TREE_PUBLIC (decl))
/* Don't warn about the ABI of a function local to this TU. */
warned = true;
tree empty_arg = NULL_TREE;
if (! decl || ! DECL_BUILT_IN (decl))
for (i = 0; i < n; i++)
{
tree arg = CALL_EXPR_ARG (function, i);
tree type = TREE_TYPE (arg);
if (is_really_empty_class (type)
&& ! TREE_ADDRESSABLE (type))
if (is_empty_class (TREE_TYPE (arg))
&& ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
{
empty_arg = arg;
CALL_EXPR_ARG (function, i) = empty_class_arg (arg);
}
/* Warn about ABI changes for a non-final argument. */
else if (!warned && empty_arg)
{
location_t loc = EXPR_LOC_OR_LOC (empty_arg, input_location);
if (decl && !varargs_function_p (decl))
mark_for_abi_warning (decl, empty_arg);
else
warn_empty_class_abi (empty_arg, loc);
warned = true;
tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
CALL_EXPR_ARG (function, i) = arg;
}
}
@ -6889,15 +6872,6 @@ build_x_va_arg (source_location loc, tree expr, tree type)
expr = build_va_arg (loc, expr, ref);
return convert_from_reference (expr);
}
else if (is_really_empty_class (type) && !TREE_ADDRESSABLE (type))
{
/* Do the reverse of empty_class_arg. */
tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
expr = build_va_arg (loc, expr, etype);
warn_empty_class_abi (type, loc);
tree ec = build0 (EMPTY_CLASS_EXPR, type);
return build2 (COMPOUND_EXPR, type, expr, ec);
}
return build_va_arg (loc, expr, type);
}
@ -6994,75 +6968,6 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum,
return arg;
}
/* Return true iff TYPE should be passed and returned as a size 0 type rather
than its normal size, for compatibility with C. */
static bool
pass_as_empty_struct (tree type)
{
return (abi_version_at_least (10)
&& type != error_mark_node
&& COMPLETE_TYPE_P (type)
&& !TREE_ADDRESSABLE (type)
&& is_really_empty_class (type));
}
/* Adjust the value VAL of empty class type TYPE for argument passing.
Keep this synced with build_x_va_arg. */
static tree
empty_class_arg (tree val)
{
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */
tree type = TREE_TYPE (val);
tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
tree empty = build0 (EMPTY_CLASS_EXPR, etype);
return build2 (COMPOUND_EXPR, etype, val, empty);
}
/* Generate a message warning about the change in empty class parameter passing
ABI. */
static tree
empty_class_msg (tree type)
{
if (!TYPE_P (type))
type = TREE_TYPE (type);
return pp_format_to_string ("empty class %qT parameter passing ABI "
"changes in -fabi-version=10 (GCC 6)", type);
}
/* Warn immediately about the change in empty class parameter ABI. */
void
warn_empty_class_abi (tree arg, location_t loc)
{
if (!warn_abi || !abi_version_crosses (10))
return;
warning_at (loc, OPT_Wabi, "%E", empty_class_msg (arg));
}
/* Tack a warning about the change in empty class parameter ABI onto FN, so
that we get a warning if a definition or call is emitted. */
void
mark_for_abi_warning (tree fn, tree type)
{
if (!warn_abi || !abi_version_crosses (10))
return;
if (lookup_attribute ("abi warning", DECL_ATTRIBUTES (fn)))
return;
tree msg = empty_class_msg (type);
msg = build_tree_list (NULL_TREE, msg);
DECL_ATTRIBUTES (fn) = tree_cons (get_identifier ("abi warning"), msg,
DECL_ATTRIBUTES (fn));
}
/* Returns the type which will really be used for passing an argument of
type TYPE. */
@ -7081,8 +6986,6 @@ type_passed_as (tree type)
&& COMPLETE_TYPE_P (type)
&& tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
type = integer_type_node;
else if (pass_as_empty_struct (type))
type = empty_struct_type;
return type;
}

View File

@ -1150,8 +1150,6 @@ enum cp_tree_index
CPTI_NULLPTR,
CPTI_NULLPTR_TYPE,
CPTI_EMPTY_STRUCT,
CPTI_MAX
};
@ -1187,7 +1185,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
#define nullptr_node cp_global_trees[CPTI_NULLPTR]
#define nullptr_type_node cp_global_trees[CPTI_NULLPTR_TYPE]
#define empty_struct_type cp_global_trees[CPTI_EMPTY_STRUCT]
/* We cache these tree nodes so as to call get_identifier less
frequently. */
@ -5540,8 +5537,6 @@ extern tree build_addr_func (tree, tsubst_flags_t);
extern void set_flags_from_callee (tree);
extern tree build_call_a (tree, int, tree*);
extern tree build_call_n (tree, int, ...);
extern void mark_for_abi_warning (tree, tree);
extern void warn_empty_class_abi (tree, location_t);
extern bool null_ptr_cst_p (tree);
extern bool null_member_pointer_value_p (tree);
extern bool sufficient_parms_p (const_tree);
@ -5896,7 +5891,6 @@ extern bool pedwarn_cxx98 (location_t, int, const char *,
extern location_t location_of (tree);
extern void qualified_name_lookup_error (tree, tree, tree,
location_t);
extern tree pp_format_to_string (const char *, ...);
/* in except.c */
extern void init_exception_processing (void);

View File

@ -4180,10 +4180,6 @@ cxx_init_decl_processing (void)
nullptr_node = build_int_cst (nullptr_type_node, 0);
}
empty_struct_type = make_node (RECORD_TYPE);
finish_builtin_struct (empty_struct_type, "__empty_struct",
NULL_TREE, NULL_TREE);
abort_fndecl
= build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
ECF_NORETURN | ECF_NOTHROW);
@ -14375,34 +14371,16 @@ store_parm_decls (tree current_function_parms)
they end in the correct forward order. */
specparms = nreverse (specparms);
/* Don't warn about the ABI of a function local to this TU. */
bool warned = !TREE_PUBLIC (current_function_decl);
bool saw_nonempty = false;
for (parm = specparms; parm; parm = next)
{
next = DECL_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
tree type = TREE_TYPE (parm);
if (DECL_NAME (parm) == NULL_TREE
|| !VOID_TYPE_P (type))
|| !VOID_TYPE_P (parm))
pushdecl (parm);
else
error ("parameter %qD declared void", parm);
/* If this isn't the last parameter, maybe warn about ABI change
in passing empty classes. */
if (processing_template_decl)
continue;
if (TREE_ADDRESSABLE (type)
|| !is_really_empty_class (type))
saw_nonempty = true;
else if (!warned
&& (saw_nonempty
|| varargs_function_p (current_function_decl)))
{
mark_for_abi_warning (current_function_decl, type);
warned = true;
}
}
else
{

View File

@ -3718,25 +3718,3 @@ qualified_name_lookup_error (tree scope, tree name,
suggest_alternatives_for (location, name);
}
}
/* Like error et al, but return the formatted message as a STRING_CST. */
tree
pp_format_to_string (const char *msg, ...)
{
pretty_printer *pp = global_dc->printer;
text_info text;
va_list ap;
va_start (ap, msg);
text.err_no = errno;
text.args_ptr = &ap;
text.format_spec = msg;
pp_format (pp, &text);
pp_output_formatted_text (pp);
va_end (ap);
const char *fmt = pp_formatted_text (pp);
tree str = build_string (strlen (fmt) + 1, fmt);
pp_clear_output_area (pp);
return str;
}

View File

@ -10579,13 +10579,6 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
0, "%Kcall to %qs declared with attribute warning: %s",
exp, identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 1)),
TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
if (warn_abi && fndecl
&& (attr = lookup_attribute ("abi warning",
DECL_ATTRIBUTES (fndecl))) != NULL)
warning_at (tree_nonartificial_location (exp),
OPT_Wabi, "%Kcall to %qs: %s",
exp, identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 1)),
TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
/* Check for a built-in function. */
if (fndecl && DECL_BUILT_IN (fndecl))

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty12a.c" }
// { dg-prune-output "command line option" }
#include "empty12.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,9 +0,0 @@
struct dummy { };
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty12.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-x c -fabi-version=9" }
// { dg-additional-sources "empty13a.c" }
// { dg-prune-output "command line option" }
#include "empty13.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f);
return 0;
}

View File

@ -1,9 +0,0 @@
struct dummy { };
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty13.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 == -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty14a.c" }
// { dg-prune-output "command line option" }
#include "empty14.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,10 +0,0 @@
struct dummy0 { };
struct dummy { struct dummy0 d[140]; };
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty14.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty15a.c" }
// { dg-prune-output "command line option" }
#include "empty15.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,30 +0,0 @@
struct A1 {};
struct A2 {};
struct B1 { struct A1 a; struct A2 b; };
struct B2 { struct A1 a; struct A2 b; };
struct C1 { struct B1 a; struct B2 b; };
struct C2 { struct B1 a; struct B2 b; };
struct D1 { struct C1 a; struct C2 b; };
struct D2 { struct C1 a; struct C2 b; };
struct E1 { struct D1 a; struct D2 b; };
struct E2 { struct D1 a; struct D2 b; };
struct F1 { struct E1 a; struct E2 b; };
struct F2 { struct E1 a; struct E2 b; };
struct G1 { struct F1 a; struct F2 b; };
struct G2 { struct F1 a; struct F2 b; };
struct H1 { struct G1 a; struct G2 b; };
struct H2 { struct G1 a; struct G2 b; };
struct I1 { struct H1 a; struct H2 b; };
struct I2 { struct H1 a; struct H2 b; };
struct J1 { struct I1 a; struct I2 b; };
struct J2 { struct I1 a; struct I2 b; };
struct dummy { struct J1 a; struct J2 b; };
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty15.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty16a.c" }
// { dg-prune-output "command line option" }
#include "empty16.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,16 +0,0 @@
#ifdef __cplusplus
struct A1 {};
struct A2 {};
struct dummy : A1, A2 {} ;
#else
struct dummy {};
#endif
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty16.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty17a.c" }
// { dg-prune-output "command line option" }
#include "empty17.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,27 +0,0 @@
#ifdef __cplusplus
struct A1
{
void foo (void);
unsigned int : 15;
};
struct A2
{
void bar (void);
unsigned int : 15;
};
struct dummy : A1, A2
{
unsigned int : 15;
};
#else
struct dummy {};
#endif
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty17.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty18a.c" }
// { dg-prune-output "command line option" }
#include "empty18.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,9 +0,0 @@
struct dummy { int d[0]; };
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty18.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,17 +0,0 @@
// PR c++/60336
// { dg-do run }
// { dg-options "-Wabi=9 -x c" }
// { dg-additional-sources "empty19a.c" }
// { dg-prune-output "command line option" }
#include "empty19.h"
extern "C" void fun(struct dummy, struct foo);
int main()
{
struct dummy d;
struct foo f = { -1, -2, -3, -4, -5 };
fun(d, f); // { dg-warning "empty" }
return 0;
}

View File

@ -1,10 +0,0 @@
struct dummy0 { };
struct dummy { struct dummy0 d[0]; };
struct foo
{
int i1;
int i2;
int i3;
int i4;
int i5;
};

View File

@ -1,6 +0,0 @@
#include "empty19.h"
void fun(struct dummy d, struct foo f)
{
if (f.i1 != -1)
__builtin_abort();
}

View File

@ -1,25 +0,0 @@
// { dg-options "-Wabi=9 -O0" }
struct A { };
void f(A, A) { } // No warning, trailing parms all empty
void f(A, A, int) { } // { dg-warning "ABI" }
__attribute__ ((always_inline))
inline void f(A a, int i) { } // No warning, always inlined
__attribute__ ((always_inline))
inline void f2(A a, int i) // But the call within the fn gets a warning
{ // when it's inlined into main
f(a,a,i); // { dg-warning "ABI" }
}
inline void f3(A a, int i) // This one is never called
{
f(a,a,i);
}
int main()
{
A a;
f(a,a);
f(a,a,42); // { dg-warning "ABI" }
f(a,42);
f2(a,42);
}

View File

@ -1,21 +0,0 @@
// { dg-options "-Wabi=9" }
#include <stdarg.h>
struct A { };
void f(int i, ...)
{
va_list ap;
va_start (ap, i);
if (i >= 1)
va_arg (ap, A); // { dg-warning "ABI" }
if (i >= 2)
va_arg (ap, int);
}
int main()
{
f(0);
f(2, A(), 42); // { dg-warning "ABI" }
}

View File

@ -1,17 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -std=c++11 -fno-pic" }
// { dg-require-effective-target fpic }
struct dummy { };
struct true_type { struct dummy i; };
extern true_type y;
extern void xxx (true_type c);
void
yyy (void)
{
xxx (y);
}
// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }

View File

@ -1,50 +0,0 @@
// { dg-do run }
// { dg-options "-O2" }
#include <stdarg.h>
struct dummy0 { };
struct dummy1 { };
struct dummy : dummy0, dummy1 { };
void
test (struct dummy a, int m, ...)
{
va_list va_arglist;
int i;
int count = 0;
if (m == 0)
count++;
va_start (va_arglist, m);
i = va_arg (va_arglist, int);
if (i == 1)
count++;
i = va_arg (va_arglist, int);
if (i == 2)
i = va_arg (va_arglist, int);
count++;
if (i == 3)
count++;
i = va_arg (va_arglist, int);
if (i == 4)
count++;
i = va_arg (va_arglist, int);
if (i == 5)
count++;
i = va_arg (va_arglist, int);
if (i == 6)
count++;
va_end (va_arglist);
if (count != 7)
__builtin_abort ();
}
struct dummy a0;
int
main ()
{
test (a0, 0, 1, 2, 3, 4, 5, 6);
return 0;
}

View File

@ -1,56 +0,0 @@
// { dg-do run }
// { dg-options "-O2" }
#include <stdarg.h>
struct dummy0
{
void bar (void);
};
struct dummy1
{
void foo (void);
};
struct dummy : dummy0, dummy1 { };
void
test (struct dummy a, int m, ...)
{
va_list va_arglist;
int i;
int count = 0;
if (m == 0)
count++;
va_start (va_arglist, m);
i = va_arg (va_arglist, int);
if (i == 1)
count++;
i = va_arg (va_arglist, int);
if (i == 2)
i = va_arg (va_arglist, int);
count++;
if (i == 3)
count++;
i = va_arg (va_arglist, int);
if (i == 4)
count++;
i = va_arg (va_arglist, int);
if (i == 5)
count++;
i = va_arg (va_arglist, int);
if (i == 6)
count++;
va_end (va_arglist);
if (count != 7)
__builtin_abort ();
}
struct dummy a0;
int
main ()
{
test (a0, 0, 1, 2, 3, 4, 5, 6);
return 0;
}

View File

@ -1,57 +0,0 @@
// { dg-do run }
// { dg-options "-O2" }
#include <stdarg.h>
struct dummy0
{
};
struct dummy1
{
unsigned : 15;
};
struct dummy : dummy0, dummy1
{
};
void
test (struct dummy a, int m, ...)
{
va_list va_arglist;
int i;
int count = 0;
if (m == 0)
count++;
va_start (va_arglist, m);
i = va_arg (va_arglist, int);
if (i == 1)
count++;
i = va_arg (va_arglist, int);
if (i == 2)
i = va_arg (va_arglist, int);
count++;
if (i == 3)
count++;
i = va_arg (va_arglist, int);
if (i == 4)
count++;
i = va_arg (va_arglist, int);
if (i == 5)
count++;
i = va_arg (va_arglist, int);
if (i == 6)
count++;
va_end (va_arglist);
if (count != 7)
__builtin_abort ();
}
struct dummy a0;
int
main ()
{
test (a0, 0, 1, 2, 3, 4, 5, 6);
return 0;
}

View File

@ -1,48 +0,0 @@
// { dg-do run }
// { dg-options "-O2 -Wabi=9" }
#include <stdarg.h>
struct dummy { };
void
test (struct dummy a, int m, ...) // { dg-message "empty" }
{
va_list va_arglist;
int i;
int count = 0;
if (m == 0)
count++;
va_start (va_arglist, m);
i = va_arg (va_arglist, int);
if (i == 1)
count++;
i = va_arg (va_arglist, int);
if (i == 2)
i = va_arg (va_arglist, int);
count++;
if (i == 3)
count++;
i = va_arg (va_arglist, int);
if (i == 4)
count++;
i = va_arg (va_arglist, int);
if (i == 5)
count++;
i = va_arg (va_arglist, int);
if (i == 6)
count++;
va_end (va_arglist);
if (count != 7)
__builtin_abort ();
}
struct dummy a0;
int
main ()
{
test (a0, 0, 1, 2, 3, 4, 5, 6); // { dg-message "empty" }
return 0;
}

View File

@ -1,15 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -Wabi=9" }
struct dummy { struct{}__attribute__((aligned (4))) a[7]; };
extern void test1 (struct dummy, ...);
extern void (*test2) (struct dummy, ...);
void
foo ()
{
struct dummy a0;
test1 (a0, 42); // { dg-message "empty" }
test2 (a0, 42); // { dg-message "empty" }
}

View File

@ -1,48 +0,0 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-O2 -fabi-version=9" }
#include <stdarg.h>
struct dummy { };
void
test (struct dummy a, int m, ...)
{
va_list va_arglist;
int i;
int count = 0;
if (m == 0)
count++;
va_start (va_arglist, m);
i = va_arg (va_arglist, int);
if (i == 1)
count++;
i = va_arg (va_arglist, int);
if (i == 2)
i = va_arg (va_arglist, int);
count++;
if (i == 3)
count++;
i = va_arg (va_arglist, int);
if (i == 4)
count++;
i = va_arg (va_arglist, int);
if (i == 5)
count++;
i = va_arg (va_arglist, int);
if (i == 6)
count++;
va_end (va_arglist);
if (count == 7)
__builtin_abort ();
}
struct dummy a0;
int
main ()
{
test (a0, 0, 1, 2, 3, 4, 5, 6);
return 0;
}

View File

@ -1,17 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -std=c++11 -fno-pic" }
// { dg-require-effective-target fpic }
struct dummy { };
struct true_type { struct dummy i; struct dummy j; };
extern true_type y;
extern void xxx (true_type c);
void
yyy (void)
{
xxx (y);
}
// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }

View File

@ -1,17 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -std=c++11 -fno-pic" }
// { dg-require-effective-target fpic }
struct dummy { };
struct true_type { struct dummy i1; struct dummy i2; };
extern true_type y;
extern void xxx (true_type c);
void
yyy (void)
{
xxx (y);
}
// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }

View File

@ -1,17 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -std=c++11 -fno-pic" }
// { dg-require-effective-target fpic }
struct dummy { };
struct true_type { struct dummy i[120]; };
extern true_type y;
extern void xxx (true_type c);
void
yyy (void)
{
xxx (y);
}
// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }

View File

@ -1,15 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -Wabi=9" }
struct dummy { struct{} a[7][3]; };
extern void test1 (struct dummy, ...);
extern void (*test2) (struct dummy, ...);
void
foo ()
{
struct dummy a0;
test1 (a0, 42); // { dg-message "empty" }
test2 (a0, 42); // { dg-message "empty" }
}

View File

@ -1,28 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -std=c++11 -fno-pic" }
// { dg-require-effective-target fpic }
struct A1 {}; struct A2 {};
struct B1 { A1 a; A2 b; }; struct B2 { A1 a; A2 b; };
struct C1 { B1 a; B2 b; }; struct C2 { B1 a; B2 b; };
struct D1 { C1 a; C2 b; }; struct D2 { C1 a; C2 b; };
struct E1 { D1 a; D2 b; }; struct E2 { D1 a; D2 b; };
struct F1 { E1 a; E2 b; }; struct F2 { E1 a; E2 b; };
struct G1 { F1 a; F2 b; }; struct G2 { F1 a; F2 b; };
struct H1 { G1 a; G2 b; }; struct H2 { G1 a; G2 b; };
struct I1 { H1 a; H2 b; }; struct I2 { H1 a; H2 b; };
struct J1 { I1 a; I2 b; }; struct J2 { I1 a; I2 b; };
struct dummy { J1 a; J2 b; };
struct true_type { struct dummy i; };
extern true_type y;
extern void xxx (true_type c);
void
yyy (void)
{
xxx (y);
}
// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }

View File

@ -1,24 +0,0 @@
// { dg-do compile }
// { dg-options "-O2 -std=c++11 -fno-pic" }
// { dg-require-effective-target fpic }
template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
constexpr operator value_type() const { return value; }
};
typedef integral_constant<bool, true> true_type;
extern void xxx (true_type c);
void
yyy (void)
{
true_type y;
xxx (y);
}
// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx17integral_constantIbLb1EE" { target i?86-*-* x86_64-*-* } } }

View File

@ -1,3 +1,7 @@
2016-04-14 Jason Merrill <jason@redhat.com>
Revert Jonathan's empty ABI change from yesterday.
2016-04-13 Martin Sebor <msebor@redhat.com>
PR c++/69517

View File

@ -84,32 +84,13 @@
# define _GLIBCXX_DEPRECATED
#endif
#if __cplusplus
// Macros for ABI tag attributes.
#ifndef _GLIBCXX_ABI_TAG_CXX11
# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11")))
#endif
#if __GXX_ABI_VERSION >= 1010
namespace std
{
inline namespace _V2 { }
}
# define _GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES \
_GLIBCXX_END_NAMESPACE_VERSION \
namespace _V2 { \
_GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_END_NAMESPACE_EMPTY_TYPES \
_GLIBCXX_END_NAMESPACE_VERSION \
} \
_GLIBCXX_BEGIN_NAMESPACE_VERSION
# define _GLIBCXX_ABI_TAG_EMPTY __attribute ((__abi_tag__ ("cxxempty")))
#else
# define _GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES
# define _GLIBCXX_END_NAMESPACE_EMPTY_TYPES
# define _GLIBCXX_ABI_TAG_EMPTY
#endif
#if __cplusplus
// Macro for constexpr, to support in mixed 03/0x mode.
#ifndef _GLIBCXX_CONSTEXPR

View File

@ -663,26 +663,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert_multi_node(__node_type* __hint,
__hash_code __code, __node_type* __n);
template<bool _Uniq, typename... _Args>
typename enable_if<_Uniq, std::pair<iterator, bool>>::type
_M_emplace(__bool_constant<_Uniq>, _Args&&... __args);
template<typename... _Args>
std::pair<iterator, bool>
_M_emplace(std::true_type, _Args&&... __args);
template<bool _Uniq, typename... _Args>
typename enable_if<!_Uniq, iterator>::type
_M_emplace(__bool_constant<_Uniq> __uk, _Args&&... __args)
{
return _M_emplace_hint(cend(), __uk, std::forward<_Args>(__args)...);
}
template<typename... _Args>
iterator
_M_emplace(std::false_type __uk, _Args&&... __args)
{ return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
// Emplace with hint, useless when keys are unique.
template<typename... _Args>
iterator
_M_emplace_hint(const_iterator, std::true_type __uk, _Args&&... __args)
_M_emplace(const_iterator, std::true_type __uk, _Args&&... __args)
{ return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
template<typename... _Args>
iterator
_M_emplace_hint(const_iterator, std::false_type, _Args&&... __args);
_M_emplace(const_iterator, std::false_type, _Args&&... __args);
template<typename _Arg, typename _NodeGenerator>
std::pair<iterator, bool>
@ -714,10 +712,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _NodeGenerator&, std::false_type);
size_type
_M_erase(const key_type&, std::true_type);
_M_erase(std::true_type, const key_type&);
size_type
_M_erase(const key_type&, std::false_type);
_M_erase(std::false_type, const key_type&);
iterator
_M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n);
@ -733,8 +731,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
iterator
emplace_hint(const_iterator __hint, _Args&&... __args)
{
return _M_emplace_hint(__hint, __unique_keys(),
std::forward<_Args>(__args)...);
return _M_emplace(__hint, __unique_keys(),
std::forward<_Args>(__args)...);
}
// Insert member functions via inheritance.
@ -750,7 +748,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_type
erase(const key_type& __k)
{ return _M_erase(__k, __unique_keys()); }
{ return _M_erase(__unique_keys(), __k); }
iterator
erase(const_iterator, const_iterator);
@ -1504,12 +1502,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Alloc, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
typename _Traits>
template<bool _Uniq, typename... _Args>
template<typename... _Args>
auto
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
_M_emplace(__bool_constant<_Uniq>, _Args&&... __args)
-> typename enable_if<_Uniq, pair<iterator, bool>>::type
_M_emplace(std::true_type, _Args&&... __args)
-> pair<iterator, bool>
{
// First build the node to get access to the hash code
__node_type* __node = this->_M_allocate_node(std::forward<_Args>(__args)...);
@ -1546,7 +1544,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
_M_emplace_hint(const_iterator __hint, std::false_type, _Args&&... __args)
_M_emplace(const_iterator __hint, std::false_type, _Args&&... __args)
-> iterator
{
// First build the node to get its hash code.
@ -1771,7 +1769,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
_M_erase(const key_type& __k, std::true_type)
_M_erase(std::true_type, const key_type& __k)
-> size_type
{
__hash_code __code = this->_M_hash_code(__k);
@ -1795,7 +1793,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, _Traits>::
_M_erase(const key_type& __k, std::false_type)
_M_erase(std::false_type, const key_type& __k)
-> size_type
{
__hash_code __code = this->_M_hash_code(__k);

View File

@ -906,8 +906,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
insert(const_iterator __hint, _Pair&& __v)
{
__hashtable& __h = this->_M_conjure_hashtable();
return __h._M_emplace_hint(__hint, __unique_keys(),
std::forward<_Pair>(__v));
return __h._M_emplace(__hint, __unique_keys(),
std::forward<_Pair>(__v));
}
};

View File

@ -166,7 +166,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* __shared_ptr will release __p by calling __d(__p)
*/
template<typename _Tp1, typename _Deleter, typename _Alloc>
_GLIBCXX_ABI_TAG_EMPTY
shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
@ -186,7 +185,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* The last owner will call __d(__p)
*/
template<typename _Deleter, typename _Alloc>
_GLIBCXX_ABI_TAG_EMPTY
shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }

View File

@ -436,7 +436,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
public:
_GLIBCXX_ABI_TAG_EMPTY
_Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
: _M_ptr(__p), _Del_base(__d), _Alloc_base(__a)
{ }
@ -455,7 +454,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_impl(__p, __d, _Alloc()) { }
// __d(__p) must not throw.
_GLIBCXX_ABI_TAG_EMPTY
_Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
: _M_impl(__p, __d, __a) { }
@ -586,7 +584,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ }
template<typename _Ptr, typename _Deleter, typename _Alloc>
_GLIBCXX_ABI_TAG_EMPTY
__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
{
typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
@ -903,7 +900,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _Tp1, typename _Deleter, typename _Alloc>
_GLIBCXX_ABI_TAG_EMPTY
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
{
@ -918,7 +914,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ }
template<typename _Deleter, typename _Alloc>
_GLIBCXX_ABI_TAG_EMPTY
__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
{ }
@ -1044,7 +1039,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __shared_ptr(__p, __d).swap(*this); }
template<typename _Tp1, typename _Deleter, typename _Alloc>
_GLIBCXX_ABI_TAG_EMPTY
void
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }

View File

@ -4270,7 +4270,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* is true then the assignment @c *i = @p __new_value is performed.
*/
template<typename _ForwardIterator, typename _Predicate, typename _Tp>
_GLIBCXX_ABI_TAG_EMPTY
void
replace_if(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred, const _Tp& __new_value)

View File

@ -72,17 +72,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
#if __cplusplus >= 201103L
_GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES
/// piecewise_construct_t
struct piecewise_construct_t { explicit piecewise_construct_t() = default; };
/// piecewise_construct
constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
_GLIBCXX_END_NAMESPACE_EMPTY_TYPES
// Forward declarations.
template<typename...>
class tuple;

View File

@ -42,15 +42,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using __is_erased_or_convertible
= __or_<is_same<_Tp, __erased_type>, is_convertible<_Alloc, _Tp>>;
_GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES
/// [allocator.tag]
struct allocator_arg_t { explicit allocator_arg_t() = default; };
constexpr allocator_arg_t allocator_arg = allocator_arg_t();
_GLIBCXX_END_NAMESPACE_EMPTY_TYPES
template<typename _Tp, typename _Alloc, typename = __void_t<>>
struct __uses_allocator_helper
: false_type { };
@ -69,15 +65,11 @@ _GLIBCXX_END_NAMESPACE_EMPTY_TYPES
struct __uses_alloc_base { };
_GLIBCXX_BEGIN_NAMESPACE_EMPTY_TYPES
struct __uses_alloc0 : __uses_alloc_base
{
struct _Sink { void operator=(const void*) { } } _M_a;
};
_GLIBCXX_END_NAMESPACE_EMPTY_TYPES
template<typename _Alloc>
struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };

View File

@ -120,44 +120,36 @@ namespace __gnu_pbds
basic_hash_table(T0 t0) : base_type(t0) { }
template<typename T0, typename T1>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1) : base_type(t0, t1) { }
template<typename T0, typename T1, typename T2>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2) : base_type(t0, t1, t2) { }
template<typename T0, typename T1, typename T2, typename T3>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2, T3 t3)
: base_type(t0, t1, t2, t3) { }
template<typename T0, typename T1, typename T2, typename T3, typename T4>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4)
: base_type(t0, t1, t2, t3, t4) { }
template<typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
: base_type(t0, t1, t2, t3, t4, t5) { }
template<typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
: base_type(t0, t1, t2, t3, t4, t5, t6) { }
template<typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
: base_type(t0, t1, t2, t3, t4, t5, t6, t7) { }
template<typename T0, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
_GLIBCXX_ABI_TAG_EMPTY
basic_hash_table(T0 t0, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6,
T7 t7, T8 t8)
: base_type(t0, t1, t2, t3, t4, t5, t6, t7, t8)

View File

@ -47,5 +47,5 @@ test01()
scoped_alloc sa;
auto p = sa.allocate(1);
sa.construct(p); // this is required to be ill-formed
// { dg-error "static assertion failed" "" { target *-*-* } 97 }
// { dg-error "static assertion failed" "" { target *-*-* } 89 }
}

View File

@ -32,7 +32,7 @@ void test01()
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 892 }
// { dg-error "incomplete" "" { target *-*-* } 889 }
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 307 }

View File

@ -25,5 +25,5 @@
void test01()
{
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 891 }
// { dg-error "incomplete" "" { target *-*-* } 888 }
}

View File

@ -45,5 +45,5 @@ test01()
{
alloc_type a;
std::tuple<X> t(std::allocator_arg, a); // this is required to be ill-formed
// { dg-error "static assertion failed" "" { target *-*-* } 97 }
// { dg-error "static assertion failed" "" { target *-*-* } 89 }
}

View File

@ -44,4 +44,4 @@ void test01()
tuple<Type> t(allocator_arg, a, 1);
}
// { dg-error "static assertion failed" "" { target *-*-* } 97 }
// { dg-error "static assertion failed" "" { target *-*-* } 89 }

View File

@ -25,7 +25,7 @@
#include <vector>
// { dg-error "multiple inlined namespaces" "" { target *-*-* } 343 }
// { dg-error "multiple inlined namespaces" "" { target *-*-* } 324 }
// "template argument 1 is invalid"
// { dg-prune-output "tuple:993" }