aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-06-12 16:47:21 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-06-12 16:47:21 -0400
commit62984918665f0c82b187293ba762bc2edb32ab92 (patch)
treec0d0389e8a30820854148e9a086d0b15f452ac9f
parentca0e51a0e5983a68e47b5195b99a8805938ecc26 (diff)
downloadgcc-62984918665f0c82b187293ba762bc2edb32ab92.zip
gcc-62984918665f0c82b187293ba762bc2edb32ab92.tar.gz
gcc-62984918665f0c82b187293ba762bc2edb32ab92.tar.bz2
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
-rw-r--r--gcc/c-family/ChangeLog8
-rw-r--r--gcc/c-family/c-common.h7
-rw-r--r--gcc/c-family/c-opts.c26
-rw-r--r--gcc/c-family/c.opt8
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/call.c20
-rw-r--r--gcc/cp/cvt.c34
-rw-r--r--gcc/cp/mangle.c140
-rw-r--r--gcc/doc/invoke.texi85
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle19-1.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle3-2.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle3.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle45.C14
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle49.C8
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle52.C14
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle54.C6
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle57.C10
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle58.C6
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle62.C10
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle62a.C10
-rw-r--r--gcc/testsuite/g++.dg/abi/scoped1.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum13.C6
22 files changed, 326 insertions, 134 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index e7c87db..dd91f6b 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,11 @@
+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>
* c-family/c-common.c (handle_section_attribute): Update handling for
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 83d5dee..6bf4051 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -619,6 +619,13 @@ extern const char *constant_string_class_name;
/* 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
juggle them at link time. */
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 29e9a35..fbbc80e 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -456,6 +456,16 @@ c_common_handle_option (size_t scode, const char *arg, int value,
handle_OPT_d (arg);
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:
cpp_opts->canonical_system_headers = value;
break;
@@ -910,6 +920,22 @@ c_common_post_options (const char **pfilename)
if (flag_declone_ctor_dtor == -1)
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 we're allowing C++0x constructs, don't warn about C++98
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 76e67d7..d2e047f 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -256,6 +256,10 @@ Wabi
C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
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
C++ ObjC++ Var(warn_abi_tag) Warning
Warn if a subobject has an abi_tag attribute that the complete object type does not have
@@ -845,6 +849,10 @@ d
C ObjC C++ ObjC++ Joined
; 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
C++ ObjC++ Var(flag_access_control) Init(1)
Enforce class member access control semantics
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7bfa9dc..5fac4a5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,18 @@
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.
* class.c (walk_subobject_offsets, include_empty_classes): Likewise.
(layout_nonempty_base_or_field, end_of_class): Likewise.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ac14ce2..44e92fc 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6508,14 +6508,22 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
arg = null_pointer_node;
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)
- warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an "
- "integral type in a future version of GCC", arg_type);
- arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain);
+ tree prom = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg,
+ complain);
+ prom = cp_perform_integral_promotions (prom, 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);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 2a82723..1dec9cc 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1701,13 +1701,9 @@ type_promotes_to (tree type)
if (TREE_CODE (type) == BOOLEAN_TYPE)
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
- 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
|| type == char16_type_node
|| type == char32_type_node
@@ -1716,16 +1712,26 @@ type_promotes_to (tree type)
int precision = MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node));
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))
- warning (OPT_Wabi, "scoped enum %qT will not promote to an integral "
- "type in a future version of GCC", type);
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- type = ENUM_UNDERLYING_TYPE (type);
- if (TYPE_UNSIGNED (type)
- && ! int_fits_type_p (TYPE_MAX_VALUE (type), totype))
- type = c_common_type_for_size (precision, 1);
+ {
+ if (abi_version_crosses (6)
+ && TYPE_MODE (prom) != TYPE_MODE (type))
+ warning (OPT_Wabi, "scoped enum %qT passed through ... as "
+ "%qT before -fabi-version=6, %qT after",
+ type, prom, ENUM_UNDERLYING_TYPE (type));
+ if (!abi_version_at_least (6))
+ type = prom;
+ }
else
- type = totype;
+ type = prom;
}
else if (c_promoting_integer_type_p (type))
{
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 86319c6..ac1c1da 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -225,7 +225,6 @@ static int local_class_index (tree);
/* Control functions. */
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 *);
/* Foreign language functions. */
@@ -786,6 +785,11 @@ write_name (tree decl, const int ignore_local_scope)
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
mangled using <unscoped-name> or <unscoped-template-name>, the
latter with a special substitution. Also, a name that is
@@ -1865,6 +1869,8 @@ write_type (tree type)
write_function_type (t);
else
write_type (t);
+ if (abi_version_crosses (8))
+ G.need_abi_warning = 1;
}
else
write_type (t);
@@ -1970,9 +1976,14 @@ write_type (tree type)
a typedef or template argument can have function type
with function-cv-quals (that use the same representation),
but you can't have a pointer/reference to such a type. */
- if (abi_version_at_least (5)
- && TREE_CODE (target) == FUNCTION_TYPE)
- target = build_qualified_type (target, TYPE_UNQUALIFIED);
+ if (TREE_CODE (target) == FUNCTION_TYPE)
+ {
+ 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);
}
break;
@@ -2012,10 +2023,9 @@ write_type (tree type)
write_char ('_');
}
else
- {
- G.need_abi_warning = 1;
- write_string ("U8__vector");
- }
+ write_string ("U8__vector");
+ if (abi_version_crosses (4))
+ G.need_abi_warning = 1;
write_type (TREE_TYPE (type));
break;
@@ -2030,8 +2040,7 @@ write_type (tree type)
&& !DECLTYPE_FOR_LAMBDA_PROXY (type));
/* In ABI <5, we stripped decltype of a plain decl. */
- if (!abi_version_at_least (5)
- && DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
+ if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
{
tree expr = DECLTYPE_TYPE_EXPR (type);
tree etype = NULL_TREE;
@@ -2052,9 +2061,13 @@ write_type (tree type)
if (etype && !type_uses_auto (etype))
{
- G.need_abi_warning = 1;
- write_type (etype);
- return;
+ if (abi_version_crosses (5))
+ G.need_abi_warning = 1;
+ if (!abi_version_at_least (5))
+ {
+ write_type (etype);
+ return;
+ }
}
}
@@ -2073,6 +2086,8 @@ write_type (tree type)
write_string ("Dn");
if (abi_version_at_least (7))
++is_builtin_type;
+ if (abi_version_crosses (7))
+ G.need_abi_warning = 1;
break;
case TYPEOF_TYPE:
@@ -2621,7 +2636,7 @@ write_expression (tree expr)
write_char ('L');
write_unsigned_number (delta - 1);
}
- else
+ if (abi_version_crosses (5))
G.need_abi_warning = true;
}
write_char ('p');
@@ -2853,12 +2868,13 @@ write_expression (tree expr)
name = operator_name_info[(int) code].mangled_name;
/* We used to mangle const_cast and static_cast like a C cast. */
- if (!abi_version_at_least (6)
- && (code == CONST_CAST_EXPR
- || code == STATIC_CAST_EXPR))
+ if (code == CONST_CAST_EXPR
+ || code == STATIC_CAST_EXPR)
{
- name = operator_name_info[CAST_EXPR].mangled_name;
- G.need_abi_warning = 1;
+ if (abi_version_crosses (6))
+ G.need_abi_warning = 1;
+ if (!abi_version_at_least (6))
+ name = operator_name_info[CAST_EXPR].mangled_name;
}
if (name == NULL)
@@ -2929,7 +2945,7 @@ write_expression (tree expr)
case PREDECREMENT_EXPR:
if (abi_version_at_least (6))
write_char ('_');
- else
+ if (abi_version_crosses (6))
G.need_abi_warning = 1;
/* Fall through. */
@@ -3064,7 +3080,7 @@ write_template_arg (tree node)
{
if (abi_version_at_least (6))
node = BASELINK_FUNCTIONS (node);
- else
+ if (abi_version_crosses (6))
/* We wrongly wrapped a class-scope function in X/E. */
G.need_abi_warning = 1;
}
@@ -3077,10 +3093,9 @@ write_template_arg (tree node)
if (abi_version_at_least (6))
write_char ('J');
else
- {
- write_char ('I');
- G.need_abi_warning = 1;
- }
+ write_char ('I');
+ if (abi_version_crosses (6))
+ G.need_abi_warning = 1;
for (i = 0; i < length; ++i)
write_template_arg (TREE_VEC_ELT (args, i));
write_char ('E');
@@ -3100,12 +3115,11 @@ write_template_arg (tree node)
/* Until ABI version 3, the underscore before the mangled name
was incorrectly omitted. */
if (!abi_version_at_least (3))
- {
- G.need_abi_warning = 1;
- write_char ('Z');
- }
+ write_char ('Z');
else
write_string ("_Z");
+ if (abi_version_crosses (3))
+ G.need_abi_warning = 1;
write_encoding (node);
write_char ('E');
}
@@ -3286,13 +3300,8 @@ start_mangling (const tree entity)
warning. */
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. */
vec_safe_truncate (G.substitutions, 0);
@@ -3304,18 +3313,18 @@ finish_mangling_internal (const bool warn)
/* Like finish_mangling_internal, but return the mangled string. */
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);
}
/* Like finish_mangling_internal, but return an identifier. */
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
remove the identifier. */
return get_identifier ((const char *) obstack_base (mangle_obstack));
@@ -3373,7 +3382,7 @@ mangle_decl_string (const tree decl)
else
write_mangled_name (decl, true);
- result = finish_mangling_get_identifier (/*warn=*/true);
+ result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE)
fprintf (stderr, "mangle_decl_string = '%s'\n\n",
IDENTIFIER_POINTER (result));
@@ -3425,26 +3434,47 @@ mangle_decl (const tree decl)
&& !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_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
future mangled name for forward-compatibility. */
int save_ver;
- tree id2, alias;
-#endif
+ tree id2;
SET_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");
-#ifdef ASM_OUTPUT_DEF
save_ver = flag_abi_version;
- flag_abi_version = 0;
+ flag_abi_version = flag_abi_compat_version;
id2 = mangle_decl_string (decl);
id2 = targetm.mangle_decl_assembler_name (decl, id2);
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;
TREE_PUBLIC (alias) = TREE_PUBLIC (decl);
DECL_VISIBILITY (alias) = DECL_VISIBILITY (decl);
@@ -3471,7 +3501,7 @@ mangle_type_string (const tree type)
start_mangling (type);
write_type (type);
- result = finish_mangling (/*warn=*/false);
+ result = finish_mangling ();
if (DEBUG_MANGLE)
fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
return result;
@@ -3496,7 +3526,7 @@ mangle_special_for_type (const tree type, const char *code)
/* Add the type. */
write_type (type);
- result = finish_mangling_get_identifier (/*warn=*/false);
+ result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE)
fprintf (stderr, "mangle_special_for_type = %s\n\n",
@@ -3567,7 +3597,7 @@ mangle_ctor_vtbl_for_type (const tree type, const tree binfo)
write_char ('_');
write_type (BINFO_TYPE (binfo));
- result = finish_mangling_get_identifier (/*warn=*/false);
+ result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE)
fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n",
IDENTIFIER_POINTER (result));
@@ -3646,7 +3676,7 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
/* Scoped name. */
write_encoding (fn_decl);
- result = finish_mangling_get_identifier (/*warn=*/false);
+ result = finish_mangling_get_identifier ();
if (DEBUG_MANGLE)
fprintf (stderr, "mangle_thunk = %s\n\n", IDENTIFIER_POINTER (result));
return result;
@@ -3739,7 +3769,7 @@ mangle_guard_variable (const tree variable)
start_mangling (variable);
write_string ("_ZGV");
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
@@ -3751,7 +3781,7 @@ mangle_tls_init_fn (const tree variable)
start_mangling (variable);
write_string ("_ZTH");
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
@@ -3765,7 +3795,7 @@ mangle_tls_wrapper_fn (const tree variable)
start_mangling (variable);
write_string (TLS_WRAPPER_PREFIX);
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. */
@@ -3795,7 +3825,7 @@ mangle_ref_init_variable (const tree variable)
/* Avoid name clashes with aggregate initialization of multiple
references at once. */
write_unsigned_number (temp_count++);
- return finish_mangling_get_identifier (/*warn=*/false);
+ return finish_mangling_get_identifier ();
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4efd3e2..3c02341 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -195,7 +195,7 @@ in the following sections.
-fvtv-counts -fvtv-debug @gol
-fvisibility-ms-compat @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
-Wnoexcept -Wnon-virtual-dtor -Wreorder @gol
-Weffc++ -Wstrict-null-sentinel @gol
@@ -2023,7 +2023,7 @@ Here is a list of options that are @emph{only} for compiling C++ programs:
@item -fabi-version=@var{n}
@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
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.
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
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
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}.
+@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
@opindex fno-access-control
Turn off all access checking. This switch is mainly useful for working
@@ -2445,8 +2465,15 @@ have meanings only for C++ programs:
@item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)}
@opindex Wabi
@opindex Wno-abi
-Warn when G++ generates code that is probably not compatible with the
-vendor-neutral C++ ABI@. Although an effort has been made to warn about
+When an explicit @option{-fabi-version=@var{n}} option is used, causes
+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,
even though G++ is generating incompatible code. There may also be
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
concerned about the fact that code generated by G++ may not be binary
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
@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:
@smallexample
extern int N;
@@ -2469,14 +2503,45 @@ template <int &> struct S @{@};
void n (S<N>) @{2@}
@end smallexample
-This is fixed in @option{-fabi-version=3}.
+This was fixed in @option{-fabi-version=3}.
@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
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
It also warns about psABI-related changes. The known psABI changes at this
diff --git a/gcc/testsuite/g++.dg/abi/mangle19-1.C b/gcc/testsuite/g++.dg/abi/mangle19-1.C
index 1463d03..a888173 100644
--- a/gcc/testsuite/g++.dg/abi/mangle19-1.C
+++ b/gcc/testsuite/g++.dg/abi/mangle19-1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-fabi-version=2 -Wno-abi" }
+// { dg-options "-fabi-version=2 -Wabi" }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 15 Dec 2003 <nathan@codesourcery.com>
@@ -9,5 +9,5 @@
extern int N;
template <int &> struct S {};
-void n (S<N>) {}
+void n (S<N>) {} // { dg-warning "mangle" }
// { dg-final { scan-assembler "\n_?_Z1n1SILZ1NEE\[: \t\n\]" } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle3-2.C b/gcc/testsuite/g++.dg/abi/mangle3-2.C
index ac85fb0..538c5cb 100644
--- a/gcc/testsuite/g++.dg/abi/mangle3-2.C
+++ b/gcc/testsuite/g++.dg/abi/mangle3-2.C
@@ -1,12 +1,12 @@
// Test mangling of type casts
-// { dg-options "-fabi-version=0" }
+// { dg-options "-fabi-version=0 -Wabi=5" }
// { dg-do compile }
template<int i> class A {};
template<bool b> class B {};
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()
{
diff --git a/gcc/testsuite/g++.dg/abi/mangle3.C b/gcc/testsuite/g++.dg/abi/mangle3.C
index 5f44f76..42f8dea 100644
--- a/gcc/testsuite/g++.dg/abi/mangle3.C
+++ b/gcc/testsuite/g++.dg/abi/mangle3.C
@@ -1,12 +1,12 @@
// Test mangling of type casts
-// { dg-options "-fabi-version=2" }
+// { dg-options "-fabi-version=2 -Wabi" }
// { dg-do compile }
template<int i> class A {};
template<bool b> class B {};
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()
{
diff --git a/gcc/testsuite/g++.dg/abi/mangle45.C b/gcc/testsuite/g++.dg/abi/mangle45.C
index 5e202a2..bdedb0a 100644
--- a/gcc/testsuite/g++.dg/abi/mangle45.C
+++ b/gcc/testsuite/g++.dg/abi/mangle45.C
@@ -1,26 +1,26 @@
// Testcase for mangling of parameters used other than in a trailing return type
// { 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 g(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 { dg-warning "mangle" }
// G++ incorrectly rejects these currently.
// 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 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 (*karg (int*))[sizeof(int)];
int main()
{
- // { dg-final { scan-assembler "_Z1fIiEvT_DtfL0p_E" } }
+ // { dg-final { scan-assembler "\n_?_Z1fIiEvT_DtfL0p_E\[: \t\n\]" } }
f (1,0);
- // { dg-final { scan-assembler "_Z1gIiEvT_PFDtfL0p_EvE" } }
+ // { dg-final { scan-assembler "\n_?_Z1gIiEvT_PFDtfL0p_EvE\[: \t\n\]" } }
g (1,garg);
// h (1,0);
// i (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);
}
diff --git a/gcc/testsuite/g++.dg/abi/mangle49.C b/gcc/testsuite/g++.dg/abi/mangle49.C
index 3795c55..fae013a 100644
--- a/gcc/testsuite/g++.dg/abi/mangle49.C
+++ b/gcc/testsuite/g++.dg/abi/mangle49.C
@@ -1,10 +1,10 @@
// PR c++/49932
// { dg-do compile { target c++11 } }
-// { dg-options "-fabi-version=0" }
+// { dg-options "-fabi-version=0 -Wabi=2" }
template < typename T >
auto
-f1( T x ) // ICE on here
+f1( T x ) // { dg-warning "mangle" }
-> typename decltype( x )::type {}
template < typename T >
@@ -19,5 +19,5 @@ void g()
f2( S() );
}
-// { dg-final { scan-assembler "_Z2f1I1SENDtfp_E4typeET_" } }
-// { dg-final { scan-assembler "_Z2f2I1SENDTcvT__EE4typeES1_" } }
+// { dg-final { scan-assembler "\n_?_Z2f1I1SENDtfp_E4typeET_\[: \t\n\]" } }
+// { dg-final { scan-assembler "\n_?_Z2f2I1SENDTcvT__EE4typeES1_\[: \t\n\]" } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle52.C b/gcc/testsuite/g++.dg/abi/mangle52.C
index 2c46341..0b9a72f 100644
--- a/gcc/testsuite/g++.dg/abi/mangle52.C
+++ b/gcc/testsuite/g++.dg/abi/mangle52.C
@@ -1,13 +1,13 @@
-// { dg-options "-fabi-version=0" }
+// { dg-options "-fabi-version=0 -Wabi=2" }
template <unsigned int> struct helper {};
-// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXszscT_Li1EEE" } }
-template <class T> void check1( helper<sizeof(static_cast<T>(1))> * ) { }
-// { dg-final { scan-assembler "_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE" } }
-template <class T, T* p> void check2( helper<sizeof(const_cast<T*>(p))> * ) { }
-// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXszrcPT_Li0EEE" } }
+// { dg-final { scan-assembler "\n_?_Z6check1IiEvP6helperIXszscT_Li1EEE\[: \t\n\]" } }
+template <class T> void check1( helper<sizeof(static_cast<T>(1))> * ) { } // { dg-warning "mangle" }
+// { dg-final { scan-assembler "\n_?_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE\[: \t\n\]" } }
+template <class T, T* p> void check2( helper<sizeof(const_cast<T*>(p))> * ) { } // { dg-warning "mangle" }
+// { dg-final { scan-assembler "\n_?_Z6check3IiEvP6helperIXszrcPT_Li0EEE\[: \t\n\]" } }
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))> * ) { }
struct A{} a;
diff --git a/gcc/testsuite/g++.dg/abi/mangle54.C b/gcc/testsuite/g++.dg/abi/mangle54.C
index 926275c..ba1d3bc 100644
--- a/gcc/testsuite/g++.dg/abi/mangle54.C
+++ b/gcc/testsuite/g++.dg/abi/mangle54.C
@@ -1,15 +1,15 @@
// { dg-do compile { target c++11 } }
-// { dg-options "-fabi-version=0" }
+// { dg-options "-fabi-version=0 -Wabi=2" }
int i;
// { dg-final { scan-assembler "_Z2f1IiEDTppfp_ET_" } }
template <class T> auto f1 (T t) -> decltype(t++) { return i; }
// { 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_" } }
template <class T> auto f3 (T t) -> decltype(t--) { return i; }
// { 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()
{
diff --git a/gcc/testsuite/g++.dg/abi/mangle57.C b/gcc/testsuite/g++.dg/abi/mangle57.C
index cd59cb8..46cf377 100644
--- a/gcc/testsuite/g++.dg/abi/mangle57.C
+++ b/gcc/testsuite/g++.dg/abi/mangle57.C
@@ -1,13 +1,13 @@
// { 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);
int cmp2(char a, char b);
template<typename T, int (*cmp)(T, T)> struct A { };
-// { dg-final { scan-assembler "_Z1fIcEvR1AIT_X4cmp1EE" } }
-template <typename T> void f (A<T,cmp1> &);
-// { dg-final { scan-assembler "_Z1fIcEvR1AIT_L_Z4cmp2ccEE" } }
-template <typename T> void f (A<T,cmp2> &);
+// { dg-final { scan-assembler "\n_?_Z1fIcEvR1AIT_X4cmp1EE\[: \t\n\]" } }
+template <typename T> void f (A<T,cmp1> &) {}
+// { dg-final { scan-assembler "\n_?_Z1fIcEvR1AIT_L_Z4cmp2ccEE\[: \t\n\]" } }
+template <typename T> void f (A<T,cmp2> &) {} // { dg-warning "mangle" }
void g()
{
A<char,cmp1> a;
diff --git a/gcc/testsuite/g++.dg/abi/mangle58.C b/gcc/testsuite/g++.dg/abi/mangle58.C
index abcb3ca..f9aadc2 100644
--- a/gcc/testsuite/g++.dg/abi/mangle58.C
+++ b/gcc/testsuite/g++.dg/abi/mangle58.C
@@ -1,5 +1,5 @@
// { 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 { };
struct B {
@@ -10,9 +10,9 @@ struct B {
// { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_XsrS_4cmp1EE" } }
template <typename T> static void g (A<T,B::cmp1> &);
// { 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" } }
- 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()
diff --git a/gcc/testsuite/g++.dg/abi/mangle62.C b/gcc/testsuite/g++.dg/abi/mangle62.C
index 6dbfd78..db541ca 100644
--- a/gcc/testsuite/g++.dg/abi/mangle62.C
+++ b/gcc/testsuite/g++.dg/abi/mangle62.C
@@ -2,10 +2,10 @@
// as a substitution candidate for a function type with function-cv-quals.
// Test for the conformant behavior.
-// { dg-options -fabi-version=0 }
+// { dg-options "-fabi-version=0 -Wabi=7" }
template <class T, class U> struct A { };
-// { dg-final { scan-assembler "_Z1fP1AIKFvvEFvvEE" } }
-void f (A<void()const, void()> *){}
-// { dg-final { scan-assembler "_Z1gP1AIFvvEKFvvEE" } }
-void g (A<void(), void()const> *){}
+// { dg-final { scan-assembler "\n_?_Z1fP1AIKFvvEFvvEE\[: \t\n\]" } }
+void f (A<void()const, void()> *){} // { dg-warning "mangled name" }
+// { dg-final { scan-assembler "\n_?_Z1gP1AIFvvEKFvvEE\[: \t\n\]" } }
+void g (A<void(), void()const> *){} // { dg-warning "mangled name" }
diff --git a/gcc/testsuite/g++.dg/abi/mangle62a.C b/gcc/testsuite/g++.dg/abi/mangle62a.C
index fca1cb6..a48efd0 100644
--- a/gcc/testsuite/g++.dg/abi/mangle62a.C
+++ b/gcc/testsuite/g++.dg/abi/mangle62a.C
@@ -2,10 +2,10 @@
// as a substitution candidate for a function type with function-cv-quals.
// Test for that for backward compatibility.
-// { dg-options -fabi-version=7 }
+// { dg-options "-fabi-version=7 -Wabi" }
template <class T, class U> struct A { };
-// { dg-final { scan-assembler "_Z1fP1AIKFvvES0_E" } }
-void f (A<void()const, void()> *){}
-// { dg-final { scan-assembler "_Z1gP1AIFvvEKS0_E" } }
-void g (A<void(), void()const> *){}
+// { dg-final { scan-assembler "\n_?_Z1fP1AIKFvvES0_E\[: \t\n\]" } }
+void f (A<void()const, void()> *){} // { dg-warning "mangle" }
+// { dg-final { scan-assembler "\n_?_Z1gP1AIFvvEKS0_E\[: \t\n\]" } }
+void g (A<void(), void()const> *){} // { dg-warning "mangle" }
diff --git a/gcc/testsuite/g++.dg/abi/scoped1.C b/gcc/testsuite/g++.dg/abi/scoped1.C
new file mode 100644
index 0000000..7589ed4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/scoped1.C
@@ -0,0 +1,23 @@
+// { 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" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum13.C b/gcc/testsuite/g++.dg/cpp0x/enum13.C
index 5e4a532..8335fad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum13.C
@@ -10,12 +10,10 @@ enum struct A : short { X };
void foo(int x, ...) {
va_list vl;
__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);
}
int main() {
- foo(0, A::X); // { dg-warning "will not promote" }
+ foo(0, A::X); // { dg-warning "scoped" }
}
-
-// { dg-prune-output "note" }