Commit 62984918 by Jason Merrill Committed by Jason Merrill

Support -Wabi warning about backward compatibility.

gcc/c-family/
	* c.opt (Wabi=, fabi-compat-version): New.
	* c-opts.c (c_common_handle_option): Handle -Wabi=.
	(c_common_post_options): Handle flag_abi_compat_version default.
	Disallow -fabi-compat-version=1.
	* c-common.h (abi_version_crosses): New.
gcc/cp/
	* call.c (convert_arg_to_ellipsis): Use abi_version_crosses.
	* cvt.c (type_promotes_to): Likewise.
	* mangle.c (write_type, write_expression): Likewise.
	(write_name, write_template_arg): Likewise.
	(mangle_decl): Make alias based on flag_abi_compat_version.
	Emit -Wabi warning here.
	(finish_mangling_internal): Not here.  Drop warn parm.
	(finish_mangling_get_identifier, finish_mangling): Adjust.
	(mangle_type_string, mangle_special_for_type): Adjust.
	(mangle_ctor_vtbl_for_type, mangle_thunk): Adjust.
	(mangle_guard_variable, mangle_tls_init_fn): Adjust.
	(mangle_tls_wrapper_fn, mangle_ref_init_variable): Adjust.

From-SVN: r211594
parent ca0e51a0
2014-06-12 Jason Merrill <jason@redhat.com>
* c.opt (Wabi=, fabi-compat-version): New.
* c-opts.c (c_common_handle_option): Handle -Wabi=.
(c_common_post_options): Handle flag_abi_compat_version default.
Disallow -fabi-compat-version=1.
* c-common.h (abi_version_crosses): New.
2014-06-11 Jan Hubicka <hubicka@ucw.cz> 2014-06-11 Jan Hubicka <hubicka@ucw.cz>
* c-family/c-common.c (handle_section_attribute): Update handling for * c-family/c-common.c (handle_section_attribute): Update handling for
......
...@@ -619,6 +619,13 @@ extern const char *constant_string_class_name; ...@@ -619,6 +619,13 @@ extern const char *constant_string_class_name;
/* C++ language option variables. */ /* C++ language option variables. */
/* Return TRUE if one of {flag_abi_version,flag_abi_compat_version} is
less than N and the other is at least N, for use by -Wabi. */
#define abi_version_crosses(N) \
(abi_version_at_least(N) \
!= (flag_abi_compat_version == 0 \
|| flag_abi_compat_version >= (N)))
/* Nonzero means generate separate instantiation control files and /* Nonzero means generate separate instantiation control files and
juggle them at link time. */ juggle them at link time. */
......
...@@ -456,6 +456,16 @@ c_common_handle_option (size_t scode, const char *arg, int value, ...@@ -456,6 +456,16 @@ c_common_handle_option (size_t scode, const char *arg, int value,
handle_OPT_d (arg); handle_OPT_d (arg);
break; break;
case OPT_Wabi_:
warn_abi = true;
if (value == 1)
{
warning (0, "%<-Wabi=1%> is not supported, using =2");
value = 2;
}
flag_abi_compat_version = value;
break;
case OPT_fcanonical_system_headers: case OPT_fcanonical_system_headers:
cpp_opts->canonical_system_headers = value; cpp_opts->canonical_system_headers = value;
break; break;
...@@ -910,6 +920,22 @@ c_common_post_options (const char **pfilename) ...@@ -910,6 +920,22 @@ c_common_post_options (const char **pfilename)
if (flag_declone_ctor_dtor == -1) if (flag_declone_ctor_dtor == -1)
flag_declone_ctor_dtor = optimize_size; flag_declone_ctor_dtor = optimize_size;
if (flag_abi_compat_version == 1)
{
warning (0, "%<-fabi-compat-version=1%> is not supported, using =2");
flag_abi_compat_version = 2;
}
else if (flag_abi_compat_version == -1)
{
/* Generate compatibility aliases for ABI v2 (3.4-4.9) by default. */
flag_abi_compat_version = (flag_abi_version == 0 ? 2 : 0);
/* But don't warn about backward compatibility unless explicitly
requested with -Wabi=n. */
if (flag_abi_version == 0)
warn_abi = false;
}
if (cxx_dialect >= cxx11) if (cxx_dialect >= cxx11)
{ {
/* If we're allowing C++0x constructs, don't warn about C++98 /* If we're allowing C++0x constructs, don't warn about C++98
......
...@@ -256,6 +256,10 @@ Wabi ...@@ -256,6 +256,10 @@ Wabi
C ObjC C++ ObjC++ LTO Var(warn_abi) Warning C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
Warn about things that will change when compiling with an ABI-compliant compiler Warn about things that will change when compiling with an ABI-compliant compiler
Wabi=
C ObjC C++ ObjC++ LTO Joined RejectNegative UInteger Warning
Warn about things that change between the current -fabi-version and the specified version
Wabi-tag Wabi-tag
C++ ObjC++ Var(warn_abi_tag) Warning C++ ObjC++ Var(warn_abi_tag) Warning
Warn if a subobject has an abi_tag attribute that the complete object type does not have Warn if a subobject has an abi_tag attribute that the complete object type does not have
...@@ -845,6 +849,10 @@ d ...@@ -845,6 +849,10 @@ d
C ObjC C++ ObjC++ Joined C ObjC C++ ObjC++ Joined
; Documented in common.opt. FIXME - what about -dI, -dD, -dN and -dD? ; Documented in common.opt. FIXME - what about -dI, -dD, -dN and -dD?
fabi-compat-version=
C++ ObjC++ Joined RejectNegative UInteger Var(flag_abi_compat_version) Init(-1)
The version of the C++ ABI used for -Wabi warnings and link compatibility aliases
faccess-control faccess-control
C++ ObjC++ Var(flag_access_control) Init(1) C++ ObjC++ Var(flag_access_control) Init(1)
Enforce class member access control semantics Enforce class member access control semantics
......
2014-06-12 Jason Merrill <jason@redhat.com> 2014-06-12 Jason Merrill <jason@redhat.com>
* call.c (convert_arg_to_ellipsis): Use abi_version_crosses.
* cvt.c (type_promotes_to): Likewise.
* mangle.c (write_type, write_expression): Likewise.
(write_name, write_template_arg): Likewise.
(mangle_decl): Make alias based on flag_abi_compat_version.
Emit -Wabi warning here.
(finish_mangling_internal): Not here. Drop warn parm.
(finish_mangling_get_identifier, finish_mangling): Adjust.
(mangle_type_string, mangle_special_for_type): Adjust.
(mangle_ctor_vtbl_for_type, mangle_thunk): Adjust.
(mangle_guard_variable, mangle_tls_init_fn): Adjust.
(mangle_tls_wrapper_fn, mangle_ref_init_variable): Adjust.
* call.c (build_operator_new_call): Remove -fabi-version=1 support. * call.c (build_operator_new_call): Remove -fabi-version=1 support.
* class.c (walk_subobject_offsets, include_empty_classes): Likewise. * class.c (walk_subobject_offsets, include_empty_classes): Likewise.
(layout_nonempty_base_or_field, end_of_class): Likewise. (layout_nonempty_base_or_field, end_of_class): Likewise.
......
...@@ -6508,14 +6508,22 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain) ...@@ -6508,14 +6508,22 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
arg = null_pointer_node; arg = null_pointer_node;
else if (INTEGRAL_OR_ENUMERATION_TYPE_P (arg_type)) else if (INTEGRAL_OR_ENUMERATION_TYPE_P (arg_type))
{ {
if (SCOPED_ENUM_P (arg_type) && !abi_version_at_least (6)) if (SCOPED_ENUM_P (arg_type))
{ {
if (complain & tf_warning) tree prom = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg,
warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an " complain);
"integral type in a future version of GCC", arg_type); prom = cp_perform_integral_promotions (prom, complain);
arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain); if (abi_version_crosses (6)
&& TYPE_MODE (TREE_TYPE (prom)) != TYPE_MODE (arg_type)
&& (complain & tf_warning))
warning_at (loc, OPT_Wabi, "scoped enum %qT passed through ... as "
"%qT before -fabi-version=6, %qT after", arg_type,
TREE_TYPE (prom), ENUM_UNDERLYING_TYPE (arg_type));
if (!abi_version_at_least (6))
arg = prom;
} }
arg = cp_perform_integral_promotions (arg, complain); else
arg = cp_perform_integral_promotions (arg, complain);
} }
arg = require_complete_type_sfinae (arg, complain); arg = require_complete_type_sfinae (arg, complain);
......
...@@ -1701,13 +1701,9 @@ type_promotes_to (tree type) ...@@ -1701,13 +1701,9 @@ type_promotes_to (tree type)
if (TREE_CODE (type) == BOOLEAN_TYPE) if (TREE_CODE (type) == BOOLEAN_TYPE)
type = integer_type_node; type = integer_type_node;
/* Scoped enums don't promote, but pretend they do for backward ABI bug
compatibility wrt varargs. */
else if (SCOPED_ENUM_P (type) && abi_version_at_least (6))
;
/* Normally convert enums to int, but convert wide enums to something /* Normally convert enums to int, but convert wide enums to something
wider. */ wider. Scoped enums don't promote, but pretend they do for backward
ABI bug compatibility wrt varargs. */
else if (TREE_CODE (type) == ENUMERAL_TYPE else if (TREE_CODE (type) == ENUMERAL_TYPE
|| type == char16_type_node || type == char16_type_node
|| type == char32_type_node || type == char32_type_node
...@@ -1716,16 +1712,26 @@ type_promotes_to (tree type) ...@@ -1716,16 +1712,26 @@ type_promotes_to (tree type)
int precision = MAX (TYPE_PRECISION (type), int precision = MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)); TYPE_PRECISION (integer_type_node));
tree totype = c_common_type_for_size (precision, 0); tree totype = c_common_type_for_size (precision, 0);
tree prom = type;
if (TREE_CODE (prom) == ENUMERAL_TYPE)
prom = ENUM_UNDERLYING_TYPE (prom);
if (TYPE_UNSIGNED (prom)
&& ! int_fits_type_p (TYPE_MAX_VALUE (prom), totype))
prom = c_common_type_for_size (precision, 1);
else
prom = totype;
if (SCOPED_ENUM_P (type)) if (SCOPED_ENUM_P (type))
warning (OPT_Wabi, "scoped enum %qT will not promote to an integral " {
"type in a future version of GCC", type); if (abi_version_crosses (6)
if (TREE_CODE (type) == ENUMERAL_TYPE) && TYPE_MODE (prom) != TYPE_MODE (type))
type = ENUM_UNDERLYING_TYPE (type); warning (OPT_Wabi, "scoped enum %qT passed through ... as "
if (TYPE_UNSIGNED (type) "%qT before -fabi-version=6, %qT after",
&& ! int_fits_type_p (TYPE_MAX_VALUE (type), totype)) type, prom, ENUM_UNDERLYING_TYPE (type));
type = c_common_type_for_size (precision, 1); if (!abi_version_at_least (6))
type = prom;
}
else else
type = totype; type = prom;
} }
else if (c_promoting_integer_type_p (type)) else if (c_promoting_integer_type_p (type))
{ {
......
...@@ -225,7 +225,6 @@ static int local_class_index (tree); ...@@ -225,7 +225,6 @@ static int local_class_index (tree);
/* Control functions. */ /* Control functions. */
static inline void start_mangling (const tree); static inline void start_mangling (const tree);
static inline const char *finish_mangling (const bool);
static tree mangle_special_for_type (const tree, const char *); static tree mangle_special_for_type (const tree, const char *);
/* Foreign language functions. */ /* Foreign language functions. */
...@@ -786,6 +785,11 @@ write_name (tree decl, const int ignore_local_scope) ...@@ -786,6 +785,11 @@ write_name (tree decl, const int ignore_local_scope)
gcc_assert (context != NULL_TREE); gcc_assert (context != NULL_TREE);
if (abi_version_crosses (7)
&& ignore_local_scope
&& TREE_CODE (context) == PARM_DECL)
G.need_abi_warning = 1;
/* A decl in :: or ::std scope is treated specially. The former is /* A decl in :: or ::std scope is treated specially. The former is
mangled using <unscoped-name> or <unscoped-template-name>, the mangled using <unscoped-name> or <unscoped-template-name>, the
latter with a special substitution. Also, a name that is latter with a special substitution. Also, a name that is
...@@ -1865,6 +1869,8 @@ write_type (tree type) ...@@ -1865,6 +1869,8 @@ write_type (tree type)
write_function_type (t); write_function_type (t);
else else
write_type (t); write_type (t);
if (abi_version_crosses (8))
G.need_abi_warning = 1;
} }
else else
write_type (t); write_type (t);
...@@ -1970,9 +1976,14 @@ write_type (tree type) ...@@ -1970,9 +1976,14 @@ write_type (tree type)
a typedef or template argument can have function type a typedef or template argument can have function type
with function-cv-quals (that use the same representation), with function-cv-quals (that use the same representation),
but you can't have a pointer/reference to such a type. */ but you can't have a pointer/reference to such a type. */
if (abi_version_at_least (5) if (TREE_CODE (target) == FUNCTION_TYPE)
&& TREE_CODE (target) == FUNCTION_TYPE) {
target = build_qualified_type (target, TYPE_UNQUALIFIED); if (abi_version_crosses (5)
&& TYPE_QUALS (target) != TYPE_UNQUALIFIED)
G.need_abi_warning = 1;
if (abi_version_at_least (5))
target = build_qualified_type (target, TYPE_UNQUALIFIED);
}
write_type (target); write_type (target);
} }
break; break;
...@@ -2012,10 +2023,9 @@ write_type (tree type) ...@@ -2012,10 +2023,9 @@ write_type (tree type)
write_char ('_'); write_char ('_');
} }
else else
{ write_string ("U8__vector");
G.need_abi_warning = 1; if (abi_version_crosses (4))
write_string ("U8__vector"); G.need_abi_warning = 1;
}
write_type (TREE_TYPE (type)); write_type (TREE_TYPE (type));
break; break;
...@@ -2030,8 +2040,7 @@ write_type (tree type) ...@@ -2030,8 +2040,7 @@ write_type (tree type)
&& !DECLTYPE_FOR_LAMBDA_PROXY (type)); && !DECLTYPE_FOR_LAMBDA_PROXY (type));
/* In ABI <5, we stripped decltype of a plain decl. */ /* In ABI <5, we stripped decltype of a plain decl. */
if (!abi_version_at_least (5) if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
&& DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
{ {
tree expr = DECLTYPE_TYPE_EXPR (type); tree expr = DECLTYPE_TYPE_EXPR (type);
tree etype = NULL_TREE; tree etype = NULL_TREE;
...@@ -2052,9 +2061,13 @@ write_type (tree type) ...@@ -2052,9 +2061,13 @@ write_type (tree type)
if (etype && !type_uses_auto (etype)) if (etype && !type_uses_auto (etype))
{ {
G.need_abi_warning = 1; if (abi_version_crosses (5))
write_type (etype); G.need_abi_warning = 1;
return; if (!abi_version_at_least (5))
{
write_type (etype);
return;
}
} }
} }
...@@ -2073,6 +2086,8 @@ write_type (tree type) ...@@ -2073,6 +2086,8 @@ write_type (tree type)
write_string ("Dn"); write_string ("Dn");
if (abi_version_at_least (7)) if (abi_version_at_least (7))
++is_builtin_type; ++is_builtin_type;
if (abi_version_crosses (7))
G.need_abi_warning = 1;
break; break;
case TYPEOF_TYPE: case TYPEOF_TYPE:
...@@ -2621,7 +2636,7 @@ write_expression (tree expr) ...@@ -2621,7 +2636,7 @@ write_expression (tree expr)
write_char ('L'); write_char ('L');
write_unsigned_number (delta - 1); write_unsigned_number (delta - 1);
} }
else if (abi_version_crosses (5))
G.need_abi_warning = true; G.need_abi_warning = true;
} }
write_char ('p'); write_char ('p');
...@@ -2853,12 +2868,13 @@ write_expression (tree expr) ...@@ -2853,12 +2868,13 @@ write_expression (tree expr)
name = operator_name_info[(int) code].mangled_name; name = operator_name_info[(int) code].mangled_name;
/* We used to mangle const_cast and static_cast like a C cast. */ /* We used to mangle const_cast and static_cast like a C cast. */
if (!abi_version_at_least (6) if (code == CONST_CAST_EXPR
&& (code == CONST_CAST_EXPR || code == STATIC_CAST_EXPR)
|| code == STATIC_CAST_EXPR))
{ {
name = operator_name_info[CAST_EXPR].mangled_name; if (abi_version_crosses (6))
G.need_abi_warning = 1; G.need_abi_warning = 1;
if (!abi_version_at_least (6))
name = operator_name_info[CAST_EXPR].mangled_name;
} }
if (name == NULL) if (name == NULL)
...@@ -2929,7 +2945,7 @@ write_expression (tree expr) ...@@ -2929,7 +2945,7 @@ write_expression (tree expr)
case PREDECREMENT_EXPR: case PREDECREMENT_EXPR:
if (abi_version_at_least (6)) if (abi_version_at_least (6))
write_char ('_'); write_char ('_');
else if (abi_version_crosses (6))
G.need_abi_warning = 1; G.need_abi_warning = 1;
/* Fall through. */ /* Fall through. */
...@@ -3064,7 +3080,7 @@ write_template_arg (tree node) ...@@ -3064,7 +3080,7 @@ write_template_arg (tree node)
{ {
if (abi_version_at_least (6)) if (abi_version_at_least (6))
node = BASELINK_FUNCTIONS (node); node = BASELINK_FUNCTIONS (node);
else if (abi_version_crosses (6))
/* We wrongly wrapped a class-scope function in X/E. */ /* We wrongly wrapped a class-scope function in X/E. */
G.need_abi_warning = 1; G.need_abi_warning = 1;
} }
...@@ -3077,10 +3093,9 @@ write_template_arg (tree node) ...@@ -3077,10 +3093,9 @@ write_template_arg (tree node)
if (abi_version_at_least (6)) if (abi_version_at_least (6))
write_char ('J'); write_char ('J');
else else
{ write_char ('I');
write_char ('I'); if (abi_version_crosses (6))
G.need_abi_warning = 1; G.need_abi_warning = 1;
}
for (i = 0; i < length; ++i) for (i = 0; i < length; ++i)
write_template_arg (TREE_VEC_ELT (args, i)); write_template_arg (TREE_VEC_ELT (args, i));
write_char ('E'); write_char ('E');
...@@ -3100,12 +3115,11 @@ write_template_arg (tree node) ...@@ -3100,12 +3115,11 @@ write_template_arg (tree node)
/* Until ABI version 3, the underscore before the mangled name /* Until ABI version 3, the underscore before the mangled name
was incorrectly omitted. */ was incorrectly omitted. */
if (!abi_version_at_least (3)) if (!abi_version_at_least (3))
{ write_char ('Z');
G.need_abi_warning = 1;
write_char ('Z');
}
else else
write_string ("_Z"); write_string ("_Z");
if (abi_version_crosses (3))
G.need_abi_warning = 1;
write_encoding (node); write_encoding (node);
write_char ('E'); write_char ('E');
} }
...@@ -3286,13 +3300,8 @@ start_mangling (const tree entity) ...@@ -3286,13 +3300,8 @@ start_mangling (const tree entity)
warning. */ warning. */
static void static void
finish_mangling_internal (const bool warn) finish_mangling_internal (void)
{ {
if (warn_abi && warn && G.need_abi_warning)
warning (OPT_Wabi, "the mangled name of %qD will change in a future "
"version of GCC",
G.entity);
/* Clear all the substitutions. */ /* Clear all the substitutions. */
vec_safe_truncate (G.substitutions, 0); vec_safe_truncate (G.substitutions, 0);
...@@ -3304,18 +3313,18 @@ finish_mangling_internal (const bool warn) ...@@ -3304,18 +3313,18 @@ finish_mangling_internal (const bool warn)
/* Like finish_mangling_internal, but return the mangled string. */ /* Like finish_mangling_internal, but return the mangled string. */
static inline const char * static inline const char *
finish_mangling (const bool warn) finish_mangling (void)
{ {
finish_mangling_internal (warn); finish_mangling_internal ();
return (const char *) obstack_finish (mangle_obstack); return (const char *) obstack_finish (mangle_obstack);
} }
/* Like finish_mangling_internal, but return an identifier. */ /* Like finish_mangling_internal, but return an identifier. */
static tree static tree
finish_mangling_get_identifier (const bool warn) finish_mangling_get_identifier (void)
{ {
finish_mangling_internal (warn); finish_mangling_internal ();
/* Don't obstack_finish here, and the next start_mangling will /* Don't obstack_finish here, and the next start_mangling will
remove the identifier. */ remove the identifier. */
return get_identifier ((const char *) obstack_base (mangle_obstack)); return get_identifier ((const char *) obstack_base (mangle_obstack));
...@@ -3373,7 +3382,7 @@ mangle_decl_string (const tree decl) ...@@ -3373,7 +3382,7 @@ mangle_decl_string (const tree decl)
else else
write_mangled_name (decl, true); write_mangled_name (decl, true);
result = finish_mangling_get_identifier (/*warn=*/true); result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE) if (DEBUG_MANGLE)
fprintf (stderr, "mangle_decl_string = '%s'\n\n", fprintf (stderr, "mangle_decl_string = '%s'\n\n",
IDENTIFIER_POINTER (result)); IDENTIFIER_POINTER (result));
...@@ -3425,26 +3434,47 @@ mangle_decl (const tree decl) ...@@ -3425,26 +3434,47 @@ mangle_decl (const tree decl)
&& !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
&& !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
{ {
#ifdef ASM_OUTPUT_DEF
/* If the mangling will change in the future, emit an alias with the /* If the mangling will change in the future, emit an alias with the
future mangled name for forward-compatibility. */ future mangled name for forward-compatibility. */
int save_ver; int save_ver;
tree id2, alias; tree id2;
#endif
SET_IDENTIFIER_GLOBAL_VALUE (id, decl); SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
if (IDENTIFIER_GLOBAL_VALUE (id) != decl) if (IDENTIFIER_GLOBAL_VALUE (id) != decl)
inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=6 (or =0) " inform (DECL_SOURCE_LOCATION (decl), "a later -fabi-version= (or =0) "
"avoids this error with a change in mangling"); "avoids this error with a change in mangling");
#ifdef ASM_OUTPUT_DEF
save_ver = flag_abi_version; save_ver = flag_abi_version;
flag_abi_version = 0; flag_abi_version = flag_abi_compat_version;
id2 = mangle_decl_string (decl); id2 = mangle_decl_string (decl);
id2 = targetm.mangle_decl_assembler_name (decl, id2); id2 = targetm.mangle_decl_assembler_name (decl, id2);
flag_abi_version = save_ver; flag_abi_version = save_ver;
alias = make_alias_for (decl, id2); if (id2 == id)
return;
if (warn_abi)
{
if (flag_abi_compat_version != 0
&& abi_version_at_least (flag_abi_compat_version))
warning (OPT_Wabi, "the mangled name of %q+D changed between "
"-fabi-version=%d (%D) and -fabi-version=%d (%D)",
G.entity, flag_abi_compat_version, id2,
flag_abi_version, id);
else
warning (OPT_Wabi, "the mangled name of %q+D changes between "
"-fabi-version=%d (%D) and -fabi-version=%d (%D)",
G.entity, flag_abi_version, id,
flag_abi_compat_version, id2);
}
#ifdef ASM_OUTPUT_DEF
if (flag_abi_compat_version != 0
&& IDENTIFIER_GLOBAL_VALUE (id2))
return;
tree alias = make_alias_for (decl, id2);
SET_IDENTIFIER_GLOBAL_VALUE (id2, alias);
DECL_IGNORED_P (alias) = 1; DECL_IGNORED_P (alias) = 1;
TREE_PUBLIC (alias) = TREE_PUBLIC (decl); TREE_PUBLIC (alias) = TREE_PUBLIC (decl);
DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl); DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl);
...@@ -3471,7 +3501,7 @@ mangle_type_string (const tree type) ...@@ -3471,7 +3501,7 @@ mangle_type_string (const tree type)
start_mangling (type); start_mangling (type);
write_type (type); write_type (type);
result = finish_mangling (/*warn=*/false); result = finish_mangling ();
if (DEBUG_MANGLE) if (DEBUG_MANGLE)
fprintf (stderr, "mangle_type_string = '%s'\n\n", result); fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
return result; return result;
...@@ -3496,7 +3526,7 @@ mangle_special_for_type (const tree type, const char *code) ...@@ -3496,7 +3526,7 @@ mangle_special_for_type (const tree type, const char *code)
/* Add the type. */ /* Add the type. */
write_type (type); write_type (type);
result = finish_mangling_get_identifier (/*warn=*/false); result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE) if (DEBUG_MANGLE)
fprintf (stderr, "mangle_special_for_type = %s\n\n", fprintf (stderr, "mangle_special_for_type = %s\n\n",
...@@ -3567,7 +3597,7 @@ mangle_ctor_vtbl_for_type (const tree type, const tree binfo) ...@@ -3567,7 +3597,7 @@ mangle_ctor_vtbl_for_type (const tree type, const tree binfo)
write_char ('_'); write_char ('_');
write_type (BINFO_TYPE (binfo)); write_type (BINFO_TYPE (binfo));
result = finish_mangling_get_identifier (/*warn=*/false); result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE) if (DEBUG_MANGLE)
fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n", fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n",
IDENTIFIER_POINTER (result)); IDENTIFIER_POINTER (result));
...@@ -3646,7 +3676,7 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset, ...@@ -3646,7 +3676,7 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
/* Scoped name. */ /* Scoped name. */
write_encoding (fn_decl); write_encoding (fn_decl);
result = finish_mangling_get_identifier (/*warn=*/false); result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE) if (DEBUG_MANGLE)
fprintf (stderr, "mangle_thunk = %s\n\n", IDENTIFIER_POINTER (result)); fprintf (stderr, "mangle_thunk = %s\n\n", IDENTIFIER_POINTER (result));
return result; return result;
...@@ -3739,7 +3769,7 @@ mangle_guard_variable (const tree variable) ...@@ -3739,7 +3769,7 @@ mangle_guard_variable (const tree variable)
start_mangling (variable); start_mangling (variable);
write_string ("_ZGV"); write_string ("_ZGV");
write_guarded_var_name (variable); write_guarded_var_name (variable);
return finish_mangling_get_identifier (/*warn=*/false); return finish_mangling_get_identifier ();
} }
/* Return an identifier for the name of a thread_local initialization /* Return an identifier for the name of a thread_local initialization
...@@ -3751,7 +3781,7 @@ mangle_tls_init_fn (const tree variable) ...@@ -3751,7 +3781,7 @@ mangle_tls_init_fn (const tree variable)
start_mangling (variable); start_mangling (variable);
write_string ("_ZTH"); write_string ("_ZTH");
write_guarded_var_name (variable); write_guarded_var_name (variable);
return finish_mangling_get_identifier (/*warn=*/false); return finish_mangling_get_identifier ();
} }
/* Return an identifier for the name of a thread_local wrapper /* Return an identifier for the name of a thread_local wrapper
...@@ -3765,7 +3795,7 @@ mangle_tls_wrapper_fn (const tree variable) ...@@ -3765,7 +3795,7 @@ mangle_tls_wrapper_fn (const tree variable)
start_mangling (variable); start_mangling (variable);
write_string (TLS_WRAPPER_PREFIX); write_string (TLS_WRAPPER_PREFIX);
write_guarded_var_name (variable); write_guarded_var_name (variable);
return finish_mangling_get_identifier (/*warn=*/false); return finish_mangling_get_identifier ();
} }
/* Return true iff FN is a thread_local wrapper function. */ /* Return true iff FN is a thread_local wrapper function. */
...@@ -3795,7 +3825,7 @@ mangle_ref_init_variable (const tree variable) ...@@ -3795,7 +3825,7 @@ mangle_ref_init_variable (const tree variable)
/* Avoid name clashes with aggregate initialization of multiple /* Avoid name clashes with aggregate initialization of multiple
references at once. */ references at once. */
write_unsigned_number (temp_count++); write_unsigned_number (temp_count++);
return finish_mangling_get_identifier (/*warn=*/false); return finish_mangling_get_identifier ();
} }
......
...@@ -195,7 +195,7 @@ in the following sections. ...@@ -195,7 +195,7 @@ in the following sections.
-fvtv-counts -fvtv-debug @gol -fvtv-counts -fvtv-debug @gol
-fvisibility-ms-compat @gol -fvisibility-ms-compat @gol
-fext-numeric-literals @gol -fext-numeric-literals @gol
-Wabi -Wconversion-null -Wctor-dtor-privacy @gol -Wabi=@var{n} -Wconversion-null -Wctor-dtor-privacy @gol
-Wdelete-non-virtual-dtor -Wliteral-suffix -Wnarrowing @gol -Wdelete-non-virtual-dtor -Wliteral-suffix -Wnarrowing @gol
-Wnoexcept -Wnon-virtual-dtor -Wreorder @gol -Wnoexcept -Wnon-virtual-dtor -Wreorder @gol
-Weffc++ -Wstrict-null-sentinel @gol -Weffc++ -Wstrict-null-sentinel @gol
...@@ -2023,7 +2023,7 @@ Here is a list of options that are @emph{only} for compiling C++ programs: ...@@ -2023,7 +2023,7 @@ Here is a list of options that are @emph{only} for compiling C++ programs:
@item -fabi-version=@var{n} @item -fabi-version=@var{n}
@opindex fabi-version @opindex fabi-version
Use version @var{n} of the C++ ABI@. The default is version 2. Use version @var{n} of the C++ ABI@. The default is version 0.
Version 0 refers to the version conforming most closely to Version 0 refers to the version conforming most closely to
the C++ ABI specification. Therefore, the ABI obtained using version 0 the C++ ABI specification. Therefore, the ABI obtained using version 0
...@@ -2031,7 +2031,8 @@ will change in different versions of G++ as ABI bugs are fixed. ...@@ -2031,7 +2031,8 @@ will change in different versions of G++ as ABI bugs are fixed.
Version 1 is the version of the C++ ABI that first appeared in G++ 3.2. Version 1 is the version of the C++ ABI that first appeared in G++ 3.2.
Version 2 is the version of the C++ ABI that first appeared in G++ 3.4. Version 2 is the version of the C++ ABI that first appeared in G++
3.4, and was the default through G++ 4.9.
Version 3 corrects an error in mangling a constant address as a Version 3 corrects an error in mangling a constant address as a
template argument. template argument.
...@@ -2049,8 +2050,27 @@ behavior of C++11 scoped enums and the mangling of template argument ...@@ -2049,8 +2050,27 @@ behavior of C++11 scoped enums and the mangling of template argument
packs, const/static_cast, prefix ++ and --, and a class scope function packs, const/static_cast, prefix ++ and --, and a class scope function
used as a template argument. used as a template argument.
Version 7, which first appeared in G++ 4.8, that treats nullptr_t as a
builtin type and corrects the mangling of lambdas in default argument
scope.
Version 8, which first appeared in G++ 4.9, corrects the substitution
behavior of function types with function-cv-qualifiers.
See also @option{-Wabi}. See also @option{-Wabi}.
@item -fabi-compat-version=@var{n}
@opindex fabi-compat-version
Starting with GCC 4.5, on targets that support strong aliases, G++
works around mangling changes by creating an alias with the correct
mangled name when defining a symbol with an incorrect mangled name.
This switch specifies which ABI version to use for the alias.
With @option{-fabi-version=0} (the default), this defaults to 2. If
another ABI version is explicitly selected, this defaults to 0.
The compatibility version is also set by @option{-Wabi=@var{n}}.
@item -fno-access-control @item -fno-access-control
@opindex fno-access-control @opindex fno-access-control
Turn off all access checking. This switch is mainly useful for working Turn off all access checking. This switch is mainly useful for working
...@@ -2445,8 +2465,15 @@ have meanings only for C++ programs: ...@@ -2445,8 +2465,15 @@ have meanings only for C++ programs:
@item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)} @item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)}
@opindex Wabi @opindex Wabi
@opindex Wno-abi @opindex Wno-abi
Warn when G++ generates code that is probably not compatible with the When an explicit @option{-fabi-version=@var{n}} option is used, causes
vendor-neutral C++ ABI@. Although an effort has been made to warn about G++ to warn when it generates code that is probably not compatible with the
vendor-neutral C++ ABI@. Since G++ now defaults to
@option{-fabi-version=0}, @option{-Wabi} has no effect unless either
an older ABI version is selected (with @option{-fabi-version=@var{n}})
or an older compatibility version is selected (with
@option{-Wabi=@var{n}} or @option{-fabi-compat-version=@var{n}}).
Although an effort has been made to warn about
all such cases, there are probably some cases that are not warned about, all such cases, there are probably some cases that are not warned about,
even though G++ is generating incompatible code. There may also be even though G++ is generating incompatible code. There may also be
cases where warnings are emitted even though the code that is generated cases where warnings are emitted even though the code that is generated
...@@ -2456,12 +2483,19 @@ You should rewrite your code to avoid these warnings if you are ...@@ -2456,12 +2483,19 @@ You should rewrite your code to avoid these warnings if you are
concerned about the fact that code generated by G++ may not be binary concerned about the fact that code generated by G++ may not be binary
compatible with code generated by other compilers. compatible with code generated by other compilers.
The known incompatibilities in @option{-fabi-version=2} (the default) include: @option{-Wabi} can also be used with an explicit version number to
warn about compatibility with a particular @option{-fabi-version}
level, e.g. @option{-Wabi=2} to warn about changes relative to
@option{-fabi-version=2}. Specifying a version number also sets
@option{-fabi-compat-version=@var{n}}.
The known incompatibilities in @option{-fabi-version=2} (which was the
default from GCC 3.4 to 4.9) include:
@itemize @bullet @itemize @bullet
@item @item
A template with a non-type template parameter of reference type is A template with a non-type template parameter of reference type was
mangled incorrectly: mangled incorrectly:
@smallexample @smallexample
extern int N; extern int N;
...@@ -2469,14 +2503,45 @@ template <int &> struct S @{@}; ...@@ -2469,14 +2503,45 @@ template <int &> struct S @{@};
void n (S<N>) @{2@} void n (S<N>) @{2@}
@end smallexample @end smallexample
This is fixed in @option{-fabi-version=3}. This was fixed in @option{-fabi-version=3}.
@item @item
SIMD vector types declared using @code{__attribute ((vector_size))} are SIMD vector types declared using @code{__attribute ((vector_size))} were
mangled in a non-standard way that does not allow for overloading of mangled in a non-standard way that does not allow for overloading of
functions taking vectors of different sizes. functions taking vectors of different sizes.
The mangling is changed in @option{-fabi-version=4}. The mangling was changed in @option{-fabi-version=4}.
@item
@code{__attribute ((const))} and @code{noreturn} were mangled as type
qualifiers, and @code{decltype} of a plain declaration was folded away.
These mangling issues were fixed in @option{-fabi-version=5}.
@item
Scoped enumerators passed as arguments to a variadic function are
promoted like unscoped enumerators, causing @samp{va_arg} to complain.
On most targets this does not actually affect the parameter passing
ABI, as there is no way to pass an argument smaller than @samp{int}.
Also, the ABI changed the mangling of template argument packs,
@code{const_cast}, @code{static_cast}, prefix increment/decrement, and
a class scope function used as a template argument.
These issues were corrected in @option{-fabi-version=6}.
@item
Lambdas in default argument scope were mangled incorrectly, and the
ABI changed the mangling of nullptr_t.
These issues were corrected in @option{-fabi-version=7}.
@item
When mangling a function type with function-cv-qualifiers, the
un-qualified function type was incorrectly treated as a substitution
candidate.
This was fixed in @option{-fabi-version=8}.
@end itemize @end itemize
It also warns about psABI-related changes. The known psABI changes at this It also warns about psABI-related changes. The known psABI changes at this
......
// { dg-do compile } // { dg-do compile }
// { dg-options "-fabi-version=2 -Wno-abi" } // { dg-options "-fabi-version=2 -Wabi" }
// Copyright (C) 2003 Free Software Foundation, Inc. // Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Dec 2003 <nathan@codesourcery.com> // Contributed by Nathan Sidwell 15 Dec 2003 <nathan@codesourcery.com>
...@@ -9,5 +9,5 @@ ...@@ -9,5 +9,5 @@
extern int N; extern int N;
template <int &> struct S {}; template <int &> struct S {};
void n (S<N>) {} void n (S<N>) {} // { dg-warning "mangle" }
// { dg-final { scan-assembler "\n_?_Z1n1SILZ1NEE\[: \t\n\]" } } // { dg-final { scan-assembler "\n_?_Z1n1SILZ1NEE\[: \t\n\]" } }
// Test mangling of type casts // Test mangling of type casts
// { dg-options "-fabi-version=0" } // { dg-options "-fabi-version=0 -Wabi=5" }
// { dg-do compile } // { dg-do compile }
template<int i> class A {}; template<int i> class A {};
template<bool b> class B {}; template<bool b> class B {};
template<int i> void f(A<i> &, B<bool(i)> &) {} template<int i> void f(A<i> &, B<bool(i)> &) {}
template<int i> void g(A<i> &, B<static_cast<bool>(i)> &) {} template<int i> void g(A<i> &, B<static_cast<bool>(i)> &) {} // { dg-warning "mangle" }
int main() int main()
{ {
......
// Test mangling of type casts // Test mangling of type casts
// { dg-options "-fabi-version=2" } // { dg-options "-fabi-version=2 -Wabi" }
// { dg-do compile } // { dg-do compile }
template<int i> class A {}; template<int i> class A {};
template<bool b> class B {}; template<bool b> class B {};
template<int i> void f(A<i> &, B<bool(i)> &) {} template<int i> void f(A<i> &, B<bool(i)> &) {}
template<int i> void g(A<i> &, B<static_cast<bool>(i)> &) {} template<int i> void g(A<i> &, B<static_cast<bool>(i)> &) {} // { dg-warning "mangle" }
int main() int main()
{ {
......
// Testcase for mangling of parameters used other than in a trailing return type // Testcase for mangling of parameters used other than in a trailing return type
// { dg-do compile { target c++11 } } // { dg-do compile { target c++11 } }
// { dg-options "-fabi-version=5" } // { dg-options "-fabi-version=5 -Wabi=4" }
template<class T> void f(T p, decltype(p)) { } // L = 1 template<class T> void f(T p, decltype(p)) { } // L = 1 { dg-warning "mangle" }
template<class T> void g(T p, decltype(p) (*)()) { } // L = 1 template<class T> void g(T p, decltype(p) (*)()) { } // L = 1 { dg-warning "mangle" }
// G++ incorrectly rejects these currently. // G++ incorrectly rejects these currently.
// template<class T> void h(T p, auto (*)()->decltype(p)); // L = 1 // template<class T> void h(T p, auto (*)()->decltype(p)); // L = 1
// template<class T> void i(T p, auto (*)(T q)->decltype(q)); // L = 0 // template<class T> void i(T p, auto (*)(T q)->decltype(q)); // L = 0
// template<class T> void j(T p, auto (*)(decltype(p))->T); // L = 2 // template<class T> void j(T p, auto (*)(decltype(p))->T); // L = 2
template<class T> void k(T p, int (*(*)(T* p))[sizeof(p)]) {} // L = 1 template<class T> void k(T p, int (*(*)(T* p))[sizeof(p)]) {} // L = 1 { dg-warning "mangle" }
int garg(); int garg();
int (*karg (int*))[sizeof(int)]; int (*karg (int*))[sizeof(int)];
int main() int main()
{ {
// { dg-final { scan-assembler "_Z1fIiEvT_DtfL0p_E" } } // { dg-final { scan-assembler "\n_?_Z1fIiEvT_DtfL0p_E\[: \t\n\]" } }
f (1,0); f (1,0);
// { dg-final { scan-assembler "_Z1gIiEvT_PFDtfL0p_EvE" } } // { dg-final { scan-assembler "\n_?_Z1gIiEvT_PFDtfL0p_EvE\[: \t\n\]" } }
g (1,garg); g (1,garg);
// h (1,0); // h (1,0);
// i (1,0); // i (1,0);
// j (1,0); // j (1,0);
// { dg-final { scan-assembler "_Z1kIiEvT_PFPAszfL0p__iPS0_E" } } // { dg-final { scan-assembler "\n_?_Z1kIiEvT_PFPAszfL0p__iPS0_E\[: \t\n\]" } }
k (1,karg); k (1,karg);
} }
// PR c++/49932 // PR c++/49932
// { dg-do compile { target c++11 } } // { dg-do compile { target c++11 } }
// { dg-options "-fabi-version=0" } // { dg-options "-fabi-version=0 -Wabi=2" }
template < typename T > template < typename T >
auto auto
f1( T x ) // ICE on here f1( T x ) // { dg-warning "mangle" }
-> typename decltype( x )::type {} -> typename decltype( x )::type {}
template < typename T > template < typename T >
...@@ -19,5 +19,5 @@ void g() ...@@ -19,5 +19,5 @@ void g()
f2( S() ); f2( S() );
} }
// { dg-final { scan-assembler "_Z2f1I1SENDtfp_E4typeET_" } } // { dg-final { scan-assembler "\n_?_Z2f1I1SENDtfp_E4typeET_\[: \t\n\]" } }
// { dg-final { scan-assembler "_Z2f2I1SENDTcvT__EE4typeES1_" } } // { dg-final { scan-assembler "\n_?_Z2f2I1SENDTcvT__EE4typeES1_\[: \t\n\]" } }
// { dg-options "-fabi-version=0" } // { dg-options "-fabi-version=0 -Wabi=2" }
template <unsigned int> struct helper {}; template <unsigned int> struct helper {};
// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXszscT_Li1EEE" } } // { dg-final { scan-assembler "\n_?_Z6check1IiEvP6helperIXszscT_Li1EEE\[: \t\n\]" } }
template <class T> void check1( helper<sizeof(static_cast<T>(1))> * ) { } template <class T> void check1( helper<sizeof(static_cast<T>(1))> * ) { } // { dg-warning "mangle" }
// { dg-final { scan-assembler "_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE" } } // { dg-final { scan-assembler "\n_?_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE\[: \t\n\]" } }
template <class T, T* p> void check2( helper<sizeof(const_cast<T*>(p))> * ) { } template <class T, T* p> void check2( helper<sizeof(const_cast<T*>(p))> * ) { } // { dg-warning "mangle" }
// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXszrcPT_Li0EEE" } } // { dg-final { scan-assembler "\n_?_Z6check3IiEvP6helperIXszrcPT_Li0EEE\[: \t\n\]" } }
template <class T> void check3( helper<sizeof(reinterpret_cast<T*>(0))> * ) { } template <class T> void check3( helper<sizeof(reinterpret_cast<T*>(0))> * ) { }
// { dg-final { scan-assembler "_Z6check4I1AXadL_Z1aEEEvP6helperIXszdcPT_T0_EE" } } // { dg-final { scan-assembler "\n_?_Z6check4I1AXadL_Z1aEEEvP6helperIXszdcPT_T0_EE\[: \t\n\]" } }
template <class T, T* p> void check4( helper<sizeof(dynamic_cast<T*>(p))> * ) { } template <class T, T* p> void check4( helper<sizeof(dynamic_cast<T*>(p))> * ) { }
struct A{} a; struct A{} a;
......
// { dg-do compile { target c++11 } } // { dg-do compile { target c++11 } }
// { dg-options "-fabi-version=0" } // { dg-options "-fabi-version=0 -Wabi=2" }
int i; int i;
// { dg-final { scan-assembler "_Z2f1IiEDTppfp_ET_" } } // { dg-final { scan-assembler "_Z2f1IiEDTppfp_ET_" } }
template <class T> auto f1 (T t) -> decltype(t++) { return i; } template <class T> auto f1 (T t) -> decltype(t++) { return i; }
// { dg-final { scan-assembler "_Z2f2IiEDTpp_fp_ET_" } } // { dg-final { scan-assembler "_Z2f2IiEDTpp_fp_ET_" } }
template <class T> auto f2 (T t) -> decltype(++t) { return i; } template <class T> auto f2 (T t) -> decltype(++t) { return i; } // { dg-warning "mangle" }
// { dg-final { scan-assembler "_Z2f3IiEDTmmfp_ET_" } } // { dg-final { scan-assembler "_Z2f3IiEDTmmfp_ET_" } }
template <class T> auto f3 (T t) -> decltype(t--) { return i; } template <class T> auto f3 (T t) -> decltype(t--) { return i; }
// { dg-final { scan-assembler "_Z2f4IiEDTmm_fp_ET_" } } // { dg-final { scan-assembler "_Z2f4IiEDTmm_fp_ET_" } }
template <class T> auto f4 (T t) -> decltype(--t) { return i; } template <class T> auto f4 (T t) -> decltype(--t) { return i; } // { dg-warning "mangle" }
int main() int main()
{ {
......
// { dg-do compile { target c++11 } } // { dg-do compile { target c++11 } }
// { dg-options "-fabi-version=0" } // { dg-options "-fabi-version=0 -Wabi=2" }
template<typename T> int cmp1(T a, T b); template<typename T> int cmp1(T a, T b);
int cmp2(char a, char b); int cmp2(char a, char b);
template<typename T, int (*cmp)(T, T)> struct A { }; template<typename T, int (*cmp)(T, T)> struct A { };
// { dg-final { scan-assembler "_Z1fIcEvR1AIT_X4cmp1EE" } } // { dg-final { scan-assembler "\n_?_Z1fIcEvR1AIT_X4cmp1EE\[: \t\n\]" } }
template <typename T> void f (A<T,cmp1> &); template <typename T> void f (A<T,cmp1> &) {}
// { dg-final { scan-assembler "_Z1fIcEvR1AIT_L_Z4cmp2ccEE" } } // { dg-final { scan-assembler "\n_?_Z1fIcEvR1AIT_L_Z4cmp2ccEE\[: \t\n\]" } }
template <typename T> void f (A<T,cmp2> &); template <typename T> void f (A<T,cmp2> &) {} // { dg-warning "mangle" }
void g() void g()
{ {
A<char,cmp1> a; A<char,cmp1> a;
......
// { dg-do compile { target c++11 } } // { dg-do compile { target c++11 } }
// { dg-options "-fabi-version=0" } // { dg-options "-fabi-version=0 -Wabi=2" }
template<typename T, int (*cmp)(T, T)> struct A { }; template<typename T, int (*cmp)(T, T)> struct A { };
struct B { struct B {
...@@ -10,9 +10,9 @@ struct B { ...@@ -10,9 +10,9 @@ struct B {
// { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_XsrS_4cmp1EE" } } // { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_XsrS_4cmp1EE" } }
template <typename T> static void g (A<T,B::cmp1> &); template <typename T> static void g (A<T,B::cmp1> &);
// { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_L_ZNS_4cmp2EccEE" } } // { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_L_ZNS_4cmp2EccEE" } }
template <typename T> static void f (A<T,cmp2> &); template <typename T> static void f (A<T,cmp2> &); // { dg-warning "mangle" }
// { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_L_ZNS_4cmp2EccEE" } } // { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_L_ZNS_4cmp2EccEE" } }
template <typename T> static void g (A<T,B::cmp2> &); template <typename T> static void g (A<T,B::cmp2> &); // { dg-warning "mangle" }
}; };
void g() void g()
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
// as a substitution candidate for a function type with function-cv-quals. // as a substitution candidate for a function type with function-cv-quals.
// Test for the conformant behavior. // Test for the conformant behavior.
// { dg-options -fabi-version=0 } // { dg-options "-fabi-version=0 -Wabi=7" }
template <class T, class U> struct A { }; template <class T, class U> struct A { };
// { dg-final { scan-assembler "_Z1fP1AIKFvvEFvvEE" } } // { dg-final { scan-assembler "\n_?_Z1fP1AIKFvvEFvvEE\[: \t\n\]" } }
void f (A<void()const, void()> *){} void f (A<void()const, void()> *){} // { dg-warning "mangled name" }
// { dg-final { scan-assembler "_Z1gP1AIFvvEKFvvEE" } } // { dg-final { scan-assembler "\n_?_Z1gP1AIFvvEKFvvEE\[: \t\n\]" } }
void g (A<void(), void()const> *){} void g (A<void(), void()const> *){} // { dg-warning "mangled name" }
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
// as a substitution candidate for a function type with function-cv-quals. // as a substitution candidate for a function type with function-cv-quals.
// Test for that for backward compatibility. // Test for that for backward compatibility.
// { dg-options -fabi-version=7 } // { dg-options "-fabi-version=7 -Wabi" }
template <class T, class U> struct A { }; template <class T, class U> struct A { };
// { dg-final { scan-assembler "_Z1fP1AIKFvvES0_E" } } // { dg-final { scan-assembler "\n_?_Z1fP1AIKFvvES0_E\[: \t\n\]" } }
void f (A<void()const, void()> *){} void f (A<void()const, void()> *){} // { dg-warning "mangle" }
// { dg-final { scan-assembler "_Z1gP1AIFvvEKS0_E" } } // { dg-final { scan-assembler "\n_?_Z1gP1AIFvvEKS0_E\[: \t\n\]" } }
void g (A<void(), void()const> *){} void g (A<void(), void()const> *){} // { dg-warning "mangle" }
// { dg-do run { target c++11 } }
// { dg-options "-fabi-version=0 -Wabi=2" }
enum class A: short { a1, a2, a3 };
void f(int i, ...)
{
__builtin_va_list ap;
__builtin_va_start (ap, i);
if (__builtin_va_arg (ap, A) != A::a1) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a2) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a3) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a1) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a2) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a3) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a1) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a2) __builtin_abort(); // { dg-warning "passed" }
if (__builtin_va_arg (ap, A) != A::a3) __builtin_abort(); // { dg-warning "passed" }
}
int main()
{
f(9, A::a1, A::a2, A::a3, A::a1, A::a2, A::a3, A::a1, A::a2, A::a3); // { dg-warning "passed" }
}
...@@ -10,12 +10,10 @@ enum struct A : short { X }; ...@@ -10,12 +10,10 @@ enum struct A : short { X };
void foo(int x, ...) { void foo(int x, ...) {
va_list vl; va_list vl;
__builtin_va_start(vl, x); __builtin_va_start(vl, x);
enum A t = __builtin_va_arg(vl, enum A); // { dg-warning "promote" } enum A t = __builtin_va_arg(vl, enum A); // { dg-warning "scoped|promote" }
__builtin_va_end(vl); __builtin_va_end(vl);
} }
int main() { int main() {
foo(0, A::X); // { dg-warning "will not promote" } foo(0, A::X); // { dg-warning "scoped" }
} }
// { dg-prune-output "note" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment