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>
* c-family/c-common.c (handle_section_attribute): Update handling for
......
......@@ -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. */
......
......@@ -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
......
......@@ -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
......
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.
......
......@@ -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);
......
......@@ -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))
{
......
......@@ -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
......
// { 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\]" } }
// 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()
{
......
// 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()
{
......
// 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);
}
// 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\]" } }
// { 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;
......
// { 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()
{
......
// { 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;
......
// { 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()
......
......@@ -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" }
......@@ -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" }
// { 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 };
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" }
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