mirror of git://gcc.gnu.org/git/gcc.git
Warn about empty parameter ABI with -Wabi=9.
* call.c (empty_class_msg, mark_for_abi_warning) (warn_empty_class_abi): New. (build_call_a): Use them. * decl.c (store_parm_decls): Use mark_for_abi_warning. * error.c (pp_format_to_string): New. From-SVN: r234960
This commit is contained in:
parent
5655267ca1
commit
2ee35bea2e
|
|
@ -1,3 +1,8 @@
|
|||
2016-04-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* cfgexpand.c (pass_expand::execute): Handle attribute "abi warning".
|
||||
* expr.c (expand_expr_real_1): Likewise.
|
||||
|
||||
2016-04-13 Ilya Enkovich <ilya.enkovich@intel.com>
|
||||
|
||||
* config/i386/i386.md (kunpckhi): Swap operands.
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ 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
|
||||
|
|
@ -6221,6 +6222,15 @@ 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
2016-04-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Warn about empty parameter ABI with -Wabi=9.
|
||||
* call.c (empty_class_msg, mark_for_abi_warning)
|
||||
(warn_empty_class_abi): New.
|
||||
(build_call_a): Use them.
|
||||
* decl.c (store_parm_decls): Use mark_for_abi_warning.
|
||||
* error.c (pp_format_to_string): New.
|
||||
|
||||
Pass empty class parameters like C.
|
||||
* call.c (pass_as_empty_struct, empty_class_arg): New.
|
||||
(type_passed_as, build_x_va_arg): Use pass_as_empty_struct.
|
||||
|
|
|
|||
|
|
@ -381,6 +381,11 @@ 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++)
|
||||
{
|
||||
|
|
@ -389,8 +394,19 @@ build_call_a (tree function, int n, tree *argarray)
|
|||
if (is_really_empty_class (type)
|
||||
&& ! TREE_ADDRESSABLE (type))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return function;
|
||||
|
|
@ -6878,6 +6894,7 @@ build_x_va_arg (source_location loc, tree expr, tree 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);
|
||||
}
|
||||
|
|
@ -7005,6 +7022,47 @@ empty_class_arg (tree val)
|
|||
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. */
|
||||
|
||||
|
|
|
|||
|
|
@ -5540,6 +5540,8 @@ 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);
|
||||
|
|
@ -5894,6 +5896,7 @@ 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);
|
||||
|
|
|
|||
|
|
@ -14332,16 +14332,34 @@ 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 (parm))
|
||||
|| !VOID_TYPE_P (type))
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3718,3 +3718,25 @@ 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 = ≈
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10579,6 +10579,13 @@ 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))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
struct dummy { };
|
||||
struct foo
|
||||
{
|
||||
int i1;
|
||||
int i2;
|
||||
int i3;
|
||||
int i4;
|
||||
int i5;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty12.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
struct dummy { };
|
||||
struct foo
|
||||
{
|
||||
int i1;
|
||||
int i2;
|
||||
int i3;
|
||||
int i4;
|
||||
int i5;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty13.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 == -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
struct dummy0 { };
|
||||
struct dummy { struct dummy0 d[140]; };
|
||||
struct foo
|
||||
{
|
||||
int i1;
|
||||
int i2;
|
||||
int i3;
|
||||
int i4;
|
||||
int i5;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty14.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty15.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#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;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty16.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#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;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty17.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
struct dummy { int d[0]; };
|
||||
struct foo
|
||||
{
|
||||
int i1;
|
||||
int i2;
|
||||
int i3;
|
||||
int i4;
|
||||
int i5;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty18.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
struct dummy0 { };
|
||||
struct dummy { struct dummy0 d[0]; };
|
||||
struct foo
|
||||
{
|
||||
int i1;
|
||||
int i2;
|
||||
int i3;
|
||||
int i4;
|
||||
int i5;
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "empty19.h"
|
||||
void fun(struct dummy d, struct foo f)
|
||||
{
|
||||
if (f.i1 != -1)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// { 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);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// { 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" }
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// { 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-*-* } } }
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// { 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// { 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// { 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// { 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// { 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" }
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// { 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// { 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-*-* } } }
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// { 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-*-* } } }
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// { 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-*-* } } }
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// { 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" }
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// { 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-*-* } } }
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// { 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-*-* } } }
|
||||
Loading…
Reference in New Issue