From patchwork Thu Jun 12 20:45:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 359328 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8362C140092 for ; Fri, 13 Jun 2014 06:46:35 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=MLDzMsP3WqXCJPtcs1WC/Gjxln0CpC4XLyPjGAGZf9l1nO 1ozvpWHfIKpgD3UC7qp2CpIOzaU43gY6dWBKJk1T7aJb6A1PQGQ2bZZng/uwvrH6 Xnn03vzKub21qrOu6LVdgJ2U8hMIwEiFVD4Fai893vYFGCXzhY4W7D6DjYMGk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=yw5tAvrMnHY6qHPJi7luNIYsjfc=; b=sIcd/bsqj5W7l/mIewIB WYiBIEYwRrCiW9bW/VJHO2nFLO/upj3VXbu/Lm6z1P7cQs6SVkfX5vmcv7/RzP2H 4EZ9aXDkZCIYYU+CXbKX9eB+iWIoggP6yxUOaM1Vk+d0D4UfhOt37Re1vY6QUL5J DvpqspZMCrEuL+ZiCnYJsfg= Received: (qmail 32250 invoked by alias); 12 Jun 2014 20:46:28 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 32226 invoked by uid 89); 12 Jun 2014 20:46:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.2 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 12 Jun 2014 20:46:19 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5CKkInu020001 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 12 Jun 2014 16:46:18 -0400 Received: from [10.10.116.21] ([10.10.116.21]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5CKjtvK025185 for ; Thu, 12 Jun 2014 16:46:12 -0400 Message-ID: <539A116E.1020006@redhat.com> Date: Thu, 12 Jun 2014 16:45:34 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to add -Wabi=n Now that -fabi-version defaults to 0, -Wabi isn't very useful. But for people interested in compatibility with earlier versions, this patch allows you to say -Wabi=2 to get any relevant warnings. This patch also adjusts the compatibility aliases to default to backward compatibility with -fabi-version=2. Tested x86_64-pc-linux-gnu, applying to trunk. commit 969f9f501a5a8b7a9498464bf3bef59e685b3895 Author: Jason Merrill Date: Mon Jun 9 16:41:07 2014 -0400 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. 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/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 or , 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 struct S @{@}; void n (S) @{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 @@ -9,5 +9,5 @@ extern int N; template struct S {}; -void n (S) {} +void n (S) {} // { 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 class A {}; template class B {}; template void f(A &, B &) {} -template void g(A &, B(i)> &) {} +template void g(A &, B(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 class A {}; template class B {}; template void f(A &, B &) {} -template void g(A &, B(i)> &) {} +template void g(A &, B(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 void f(T p, decltype(p)) { } // L = 1 -template void g(T p, decltype(p) (*)()) { } // L = 1 +template void f(T p, decltype(p)) { } // L = 1 { dg-warning "mangle" } +template void g(T p, decltype(p) (*)()) { } // L = 1 { dg-warning "mangle" } // G++ incorrectly rejects these currently. // template void h(T p, auto (*)()->decltype(p)); // L = 1 // template void i(T p, auto (*)(T q)->decltype(q)); // L = 0 // template void j(T p, auto (*)(decltype(p))->T); // L = 2 -template void k(T p, int (*(*)(T* p))[sizeof(p)]) {} // L = 1 +template 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 struct helper {}; -// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXszscT_Li1EEE" } } -template void check1( helper(1))> * ) { } -// { dg-final { scan-assembler "_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE" } } -template void check2( helper(p))> * ) { } -// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXszrcPT_Li0EEE" } } +// { dg-final { scan-assembler "\n_?_Z6check1IiEvP6helperIXszscT_Li1EEE\[: \t\n\]" } } +template void check1( helper(1))> * ) { } // { dg-warning "mangle" } +// { dg-final { scan-assembler "\n_?_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE\[: \t\n\]" } } +template void check2( helper(p))> * ) { } // { dg-warning "mangle" } +// { dg-final { scan-assembler "\n_?_Z6check3IiEvP6helperIXszrcPT_Li0EEE\[: \t\n\]" } } template void check3( helper(0))> * ) { } -// { dg-final { scan-assembler "_Z6check4I1AXadL_Z1aEEEvP6helperIXszdcPT_T0_EE" } } +// { dg-final { scan-assembler "\n_?_Z6check4I1AXadL_Z1aEEEvP6helperIXszdcPT_T0_EE\[: \t\n\]" } } template void check4( helper(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 auto f1 (T t) -> decltype(t++) { return i; } // { dg-final { scan-assembler "_Z2f2IiEDTpp_fp_ET_" } } -template auto f2 (T t) -> decltype(++t) { return i; } +template auto f2 (T t) -> decltype(++t) { return i; } // { dg-warning "mangle" } // { dg-final { scan-assembler "_Z2f3IiEDTmmfp_ET_" } } template auto f3 (T t) -> decltype(t--) { return i; } // { dg-final { scan-assembler "_Z2f4IiEDTmm_fp_ET_" } } -template auto f4 (T t) -> decltype(--t) { return i; } +template 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 int cmp1(T a, T b); int cmp2(char a, char b); template struct A { }; -// { dg-final { scan-assembler "_Z1fIcEvR1AIT_X4cmp1EE" } } -template void f (A &); -// { dg-final { scan-assembler "_Z1fIcEvR1AIT_L_Z4cmp2ccEE" } } -template void f (A &); +// { dg-final { scan-assembler "\n_?_Z1fIcEvR1AIT_X4cmp1EE\[: \t\n\]" } } +template void f (A &) {} +// { dg-final { scan-assembler "\n_?_Z1fIcEvR1AIT_L_Z4cmp2ccEE\[: \t\n\]" } } +template void f (A &) {} // { dg-warning "mangle" } void g() { A 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 struct A { }; struct B { @@ -10,9 +10,9 @@ struct B { // { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_XsrS_4cmp1EE" } } template static void g (A &); // { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_L_ZNS_4cmp2EccEE" } } - template static void f (A &); + template static void f (A &); // { dg-warning "mangle" } // { dg-final { scan-assembler "_ZN1B1gIcEEvR1AIT_L_ZNS_4cmp2EccEE" } } - template static void g (A &); + template static void g (A &); // { 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 struct A { }; -// { dg-final { scan-assembler "_Z1fP1AIKFvvEFvvEE" } } -void f (A *){} -// { dg-final { scan-assembler "_Z1gP1AIFvvEKFvvEE" } } -void g (A *){} +// { dg-final { scan-assembler "\n_?_Z1fP1AIKFvvEFvvEE\[: \t\n\]" } } +void f (A *){} // { dg-warning "mangled name" } +// { dg-final { scan-assembler "\n_?_Z1gP1AIFvvEKFvvEE\[: \t\n\]" } } +void g (A *){} // { 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 struct A { }; -// { dg-final { scan-assembler "_Z1fP1AIKFvvES0_E" } } -void f (A *){} -// { dg-final { scan-assembler "_Z1gP1AIFvvEKS0_E" } } -void g (A *){} +// { dg-final { scan-assembler "\n_?_Z1fP1AIKFvvES0_E\[: \t\n\]" } } +void f (A *){} // { dg-warning "mangle" } +// { dg-final { scan-assembler "\n_?_Z1gP1AIFvvEKS0_E\[: \t\n\]" } } +void g (A *){} // { 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" }