While looking at PR 58074, I found that I wanted to be able to refer to
different ABI compatibility levels for warnings vs. mangling
compatibility aliases. Under this patch, if only one is specified it
still implies the other, but if both are specified they can be
different. I've also updated the -Wabi documentation, which was a bit
behind.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit b4ee740ab8096dda0c2b4dd1d1782a3f5efc55c2
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Sep 2 16:43:48 2015 -0400
Disconnect -Wabi=<n> from -fabi-compat-version=<n>.
gcc/c-family/
* c-common.h (abi_compat_version_crosses): New.
(warn_abi_version): Declare.
* c-common.c: Define it.
* c-opts.c (c_common_post_options): Handle it.
flag_abi_compat_version defaults to 8.
gcc/cp/
* mangle.c (abi_warn_or_compat_version_crosses): New.
Use it instead of abi_version_crosses.
(mangle_decl): Deal with -fabi-compat-version and -Wabi separately.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 4b922bf..879f4db 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -239,6 +239,9 @@ const char *constant_string_class_name;
/* C++ language option variables. */
+/* The reference version of the ABI for -Wabi. */
+
+int warn_abi_version = -1;
/* Nonzero means generate separate instantiation control files and
juggle them at link time. */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 74d1bc1..0b4d993 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -648,14 +648,24 @@ extern const char *constant_string_class_name;
/* C++ language option variables. */
+/* The reference version of the ABI for -Wabi. */
+
+extern int warn_abi_version;
/* 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) \
+ less than N and the other is at least N. */
+#define abi_compat_version_crosses(N) \
(abi_version_at_least(N) \
!= (flag_abi_compat_version == 0 \
|| flag_abi_compat_version >= (N)))
+/* Return TRUE if one of {flag_abi_version,warn_abi_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) \
+ != (warn_abi_version == 0 \
+ || warn_abi_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 f358b62..bf2e6b0 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -397,7 +397,9 @@ c_common_handle_option (size_t scode, const char *arg, int value,
warning (0, "%<-Wabi=1%> is not supported, using =2");
value = 2;
}
- flag_abi_compat_version = value;
+ warn_abi_version = value;
+ if (flag_abi_compat_version == -1)
+ flag_abi_compat_version = value;
break;
case OPT_fcanonical_system_headers:
@@ -870,6 +872,14 @@ c_common_post_options (const char **pfilename)
if (flag_declone_ctor_dtor == -1)
flag_declone_ctor_dtor = optimize_size;
+ if (warn_abi_version == -1)
+ {
+ if (flag_abi_compat_version != -1)
+ warn_abi_version = flag_abi_compat_version;
+ else
+ warn_abi_version = 0;
+ }
+
if (flag_abi_compat_version == 1)
{
warning (0, "%<-fabi-compat-version=1%> is not supported, using =2");
@@ -877,13 +887,9 @@ c_common_post_options (const char **pfilename)
}
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;
+ /* Generate compatibility aliases for ABI v8 (5.1) by default. */
+ flag_abi_compat_version
+ = (flag_abi_version == 0 ? 8 : 0);
}
/* Change flag_abi_version to be the actual current ABI level for the
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 2640d52..248d280 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -94,6 +94,11 @@ along with GCC; see the file COPYING3. If not see
|| (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
&& (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
+/* For deciding whether to set G.need_abi_warning, we need to consider both
+ warn_abi_version and flag_abi_compat_version. */
+#define abi_warn_or_compat_version_crosses(N) \
+ (abi_version_crosses (N) || abi_compat_version_crosses (N))
+
/* Things we only need one of. This module is not reentrant. */
struct GTY(()) globals {
/* An array of the current substitution candidates, in the order
@@ -829,7 +834,7 @@ write_name (tree decl, const int ignore_local_scope)
gcc_assert (context != NULL_TREE);
- if (abi_version_crosses (7)
+ if (abi_warn_or_compat_version_crosses (7)
&& ignore_local_scope
&& TREE_CODE (context) == PARM_DECL)
G.need_abi_warning = 1;
@@ -1918,7 +1923,7 @@ write_type (tree type)
write_function_type (t);
else
write_type (t);
- if (abi_version_crosses (8))
+ if (abi_warn_or_compat_version_crosses (8))
G.need_abi_warning = 1;
}
else
@@ -2027,7 +2032,7 @@ write_type (tree type)
but you can't have a pointer/reference to such a type. */
if (TREE_CODE (target) == FUNCTION_TYPE)
{
- if (abi_version_crosses (5)
+ if (abi_warn_or_compat_version_crosses (5)
&& TYPE_QUALS (target) != TYPE_UNQUALIFIED)
G.need_abi_warning = 1;
if (abi_version_at_least (5))
@@ -2073,7 +2078,7 @@ write_type (tree type)
}
else
write_string ("U8__vector");
- if (abi_version_crosses (4))
+ if (abi_warn_or_compat_version_crosses (4))
G.need_abi_warning = 1;
write_type (TREE_TYPE (type));
break;
@@ -2110,7 +2115,7 @@ write_type (tree type)
if (etype && !type_uses_auto (etype))
{
- if (abi_version_crosses (5))
+ if (abi_warn_or_compat_version_crosses (5))
G.need_abi_warning = 1;
if (!abi_version_at_least (5))
{
@@ -2135,7 +2140,7 @@ write_type (tree type)
write_string ("Dn");
if (abi_version_at_least (7))
++is_builtin_type;
- if (abi_version_crosses (7))
+ if (abi_warn_or_compat_version_crosses (7))
G.need_abi_warning = 1;
break;
@@ -2207,7 +2212,7 @@ write_CV_qualifiers_for_type (const tree type)
&& !is_attribute_p ("abi_tag", name))
vec.safe_push (a);
}
- if (abi_version_crosses (10) && !vec.is_empty ())
+ if (abi_warn_or_compat_version_crosses (10) && !vec.is_empty ())
G.need_abi_warning = true;
if (abi_version_at_least (10))
{
@@ -2747,7 +2752,7 @@ write_expression (tree expr)
write_char ('L');
write_unsigned_number (delta - 1);
}
- if (abi_version_crosses (5))
+ if (abi_warn_or_compat_version_crosses (5))
G.need_abi_warning = true;
}
write_char ('p');
@@ -2989,7 +2994,7 @@ write_expression (tree expr)
if (code == CONST_CAST_EXPR
|| code == STATIC_CAST_EXPR)
{
- if (abi_version_crosses (6))
+ if (abi_warn_or_compat_version_crosses (6))
G.need_abi_warning = 1;
if (!abi_version_at_least (6))
name = operator_name_info[CAST_EXPR].mangled_name;
@@ -3063,7 +3068,7 @@ write_expression (tree expr)
case PREDECREMENT_EXPR:
if (abi_version_at_least (6))
write_char ('_');
- if (abi_version_crosses (6))
+ if (abi_warn_or_compat_version_crosses (6))
G.need_abi_warning = 1;
/* Fall through. */
@@ -3200,7 +3205,7 @@ write_template_arg (tree node)
{
if (abi_version_at_least (6))
node = BASELINK_FUNCTIONS (node);
- if (abi_version_crosses (6))
+ if (abi_warn_or_compat_version_crosses (6))
/* We wrongly wrapped a class-scope function in X/E. */
G.need_abi_warning = 1;
}
@@ -3214,7 +3219,7 @@ write_template_arg (tree node)
write_char ('J');
else
write_char ('I');
- if (abi_version_crosses (6))
+ if (abi_warn_or_compat_version_crosses (6))
G.need_abi_warning = 1;
for (i = 0; i < length; ++i)
write_template_arg (TREE_VEC_ELT (args, i));
@@ -3238,7 +3243,7 @@ write_template_arg (tree node)
write_char ('Z');
else
write_string ("_Z");
- if (abi_version_crosses (3))
+ if (abi_warn_or_compat_version_crosses (3))
G.need_abi_warning = 1;
write_encoding (node);
write_char ('E');
@@ -3627,32 +3632,41 @@ mangle_decl (const tree decl)
}
save_ver = flag_abi_version;
+
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;
- if (id2 == id)
- return;
+ if (id2 != id)
+ note_mangling_alias (decl, id2);
if (warn_abi)
{
- if (flag_abi_compat_version != 0
- && abi_version_at_least (flag_abi_compat_version))
+ if (flag_abi_compat_version != warn_abi_version)
+ {
+ flag_abi_version = warn_abi_version;
+ id2 = mangle_decl_string (decl);
+ id2 = targetm.mangle_decl_assembler_name (decl, id2);
+ }
+
+ if (id2 == id)
+ /* OK. */;
+ else if (warn_abi_version != 0
+ && abi_version_at_least (warn_abi_version))
warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
"the mangled name of %qD changed between "
"-fabi-version=%d (%D) and -fabi-version=%d (%D)",
- G.entity, flag_abi_compat_version, id2,
+ G.entity, warn_abi_version, id2,
flag_abi_version, id);
else
warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
"the mangled name of %qD changes between "
"-fabi-version=%d (%D) and -fabi-version=%d (%D)",
G.entity, flag_abi_version, id,
- flag_abi_compat_version, id2);
+ warn_abi_version, id2);
}
- note_mangling_alias (decl, id2);
+ flag_abi_version = save_ver;
}
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 547ee2d..f0a90f6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -2134,6 +2134,13 @@ scope.
Version 8, which first appeared in G++ 4.9, corrects the substitution
behavior of function types with function-cv-qualifiers.
+Version 9, which first appeared in G++ 5.2, corrects the alignment of
+@code{nullptr_t}.
+
+Version 10, which first appeared in G++ 6.1, adds mangling of
+attributes that affect type identity, such as ia32 calling convention
+attributes (e.g. @samp{stdcall}).
+
See also @option{-Wabi}.
@item -fabi-compat-version=@var{n}
@@ -2143,10 +2150,15 @@ 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.
+With @option{-fabi-version=0} (the default), this defaults to 8 (GCC 5
+compatibility). If another ABI version is explicitly selected, this
+defaults to 0. For compatibility with GCC versions 3.2 through 4.9,
+use @option{-fabi-compat-version=2}.
-The compatibility version is also set by @option{-Wabi=@var{n}}.
+If this option is not provided but @option{-Wabi=@var{n}} is, that
+version is used for compatibility aliases. If this option is provided
+along with @option{-Wabi} (without the version), the version from this
+option is used for the warning.
@item -fno-access-control
@opindex fno-access-control
@@ -2559,13 +2571,25 @@ have meanings only for C++ programs:
@item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)}
@opindex Wabi
@opindex Wno-abi
-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}}).
+Warn when G++ it generates code that is probably not compatible with
+the vendor-neutral C++ ABI@. Since G++ now defaults to updating the
+ABI with each major release, normally @option{-Wabi} will warn only if
+there is a check added later in a release series for an ABI issue
+discovered since the initial release. @option{-Wabi} will warn about
+more things if an older ABI version is selected (with
+@option{-fabi-version=@var{n}}).
+
+@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}.
+
+If an explicit version number is provided and
+@option{-fabi-compat-version} is not specified, the version number
+from this option is used for compatibility aliases. If no explicit
+version number is provided with this option, but
+@option{-fabi-compat-version} is specified, that version number is
+used for ABI warnings.
Although an effort has been made to warn about
all such cases, there are probably some cases that are not warned about,
@@ -2577,13 +2601,7 @@ 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.
-@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
+Known incompatibilities in @option{-fabi-version=2} (which was the
default from GCC 3.4 to 4.9) include:
@itemize @bullet
@@ -2635,7 +2653,24 @@ 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}.
+This was fixed in @option{-fabi-version=8}, the default for GCC 5.1.
+
+@item
+@code{decltype(nullptr)} incorrectly had an alignment of 1, leading to
+unaligned accesses. Note that this did not affect the ABI of a
+function with a @code{nullptr_t} parameter, as parameters have a
+minimum alignment.
+
+This was fixed in @option{-fabi-version=9}, the default for GCC 5.2.
+
+@item
+Target-specific attributes that affect the identity of a type, such as
+ia32 calling conventions on a function type (stdcall, regparm, etc.),
+did not affect the mangled name, leading to name collisions when
+function pointers were used as template arguments.
+
+This was fixed in @option{-fabi-version=10}, the default for GCC 6.1.
+
@end itemize
It also warns about psABI-related changes. The known psABI changes at this