re PR c++/65046 (-Wabi-tag doesn't warn about variables or function return types)

PR c++/65046
	Automatically propagate ABI tags to variables and functions
	from their (return) type.
	* class.c (check_tag): Handle variables and functions.
	(mark_or_check_attr_tags): Split out from find_abi_tags_r.
	(mark_or_check_tags): Likewise.
	(mark_abi_tags): Use it.  Rename from mark_type_abi_tags.
	(check_abi_tags): Add single argument overload for decls.
	Handle inheriting tags for decls.
	* mangle.c (write_mangled_name): Call it.
	(mangle_return_type_p): Split out from write_encoding.
	(unmangled_name_p): Split out from write_mangled_name.
	(write_mangled_name): Ignore abi_tag on namespace.
	* cp-tree.h (NAMESPACE_IS_INLINE): Replace NAMESPACE_ABI_TAG.
	* parser.c (cp_parser_namespace_definition): Set it.
	* name-lookup.c (handle_namespace_attrs): Use arguments. Warn
	about abi_tag attribute on non-inline namespace.
	* tree.c (check_abi_tag_args): Split out from handle_abi_tag_attribute.
	(handle_abi_tag_attribute): Allow tags on variables.

From-SVN: r221521
This commit is contained in:
Jason Merrill 2015-03-19 15:31:48 -04:00 committed by Jason Merrill
parent 9b65e171ed
commit 7cb7357360
17 changed files with 369 additions and 121 deletions

View File

@ -1,3 +1,25 @@
2015-03-19 Jason Merrill <jason@redhat.com>
PR c++/65046
Automatically propagate ABI tags to variables and functions
from their (return) type.
* class.c (check_tag): Handle variables and functions.
(mark_or_check_attr_tags): Split out from find_abi_tags_r.
(mark_or_check_tags): Likewise.
(mark_abi_tags): Use it. Rename from mark_type_abi_tags.
(check_abi_tags): Add single argument overload for decls.
Handle inheriting tags for decls.
* mangle.c (write_mangled_name): Call it.
(mangle_return_type_p): Split out from write_encoding.
(unmangled_name_p): Split out from write_mangled_name.
(write_mangled_name): Ignore abi_tag on namespace.
* cp-tree.h (NAMESPACE_IS_INLINE): Replace NAMESPACE_ABI_TAG.
* parser.c (cp_parser_namespace_definition): Set it.
* name-lookup.c (handle_namespace_attrs): Use arguments. Warn
about abi_tag attribute on non-inline namespace.
* tree.c (check_abi_tag_args): Split out from handle_abi_tag_attribute.
(handle_abi_tag_attribute): Allow tags on variables.
2015-03-19 Jakub Jelinek <jakub@redhat.com>
* decl2.c (cplus_decl_attributes): Also add "omp declare target"

View File

@ -1382,44 +1382,53 @@ struct abi_tag_data
a tag NAMESPACE_DECL) or a STRING_CST (a tag attribute). */
static void
check_tag (tree tag, tree *tp, abi_tag_data *p)
check_tag (tree tag, tree id, tree *tp, abi_tag_data *p)
{
tree id;
if (TREE_CODE (tag) == STRING_CST)
id = get_identifier (TREE_STRING_POINTER (tag));
else
{
id = tag;
tag = NULL_TREE;
}
if (!IDENTIFIER_MARKED (id))
{
if (!tag)
tag = build_string (IDENTIFIER_LENGTH (id) + 1,
IDENTIFIER_POINTER (id));
if (p->tags != error_mark_node)
{
/* We're collecting tags from template arguments. */
/* We're collecting tags from template arguments or from
the type of a variable or function return type. */
p->tags = tree_cons (NULL_TREE, tag, p->tags);
ABI_TAG_IMPLICIT (p->tags) = true;
/* Don't inherit this tag multiple times. */
IDENTIFIER_MARKED (id) = true;
if (TYPE_P (p->t))
{
/* Tags inherited from type template arguments are only used
to avoid warnings. */
ABI_TAG_IMPLICIT (p->tags) = true;
return;
}
/* For functions and variables we want to warn, too. */
}
/* Otherwise we're diagnosing missing tags. */
if (TREE_CODE (p->t) == FUNCTION_DECL)
{
if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
"that %qT (used in its return type) has",
p->t, tag, *tp))
inform (location_of (*tp), "%qT declared here", *tp);
}
else if (TREE_CODE (p->t) == VAR_DECL)
{
if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
"that %qT (used in its type) has", p->t, tag, *tp))
inform (location_of (*tp), "%qT declared here", *tp);
}
else if (TYPE_P (p->subob))
{
if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
"that base %qT has", p->t, tag, p->subob))
inform (location_of (p->subob), "%qT declared here",
p->subob);
}
else
{
if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
"that %qT (used in the type of %qD) has",
p->t, tag, *tp, p->subob))
{
@ -1431,8 +1440,53 @@ check_tag (tree tag, tree *tp, abi_tag_data *p)
}
}
/* Find all the ABI tags in the attribute list ATTR and either call
check_tag (if TP is non-null) or set IDENTIFIER_MARKED to val. */
static void
mark_or_check_attr_tags (tree attr, tree *tp, abi_tag_data *p, bool val)
{
if (!attr)
return;
for (; (attr = lookup_attribute ("abi_tag", attr));
attr = TREE_CHAIN (attr))
for (tree list = TREE_VALUE (attr); list;
list = TREE_CHAIN (list))
{
tree tag = TREE_VALUE (list);
tree id = get_identifier (TREE_STRING_POINTER (tag));
if (tp)
check_tag (tag, id, tp, p);
else
IDENTIFIER_MARKED (id) = val;
}
}
/* Find all the ABI tags on T and its enclosing scopes and either call
check_tag (if TP is non-null) or set IDENTIFIER_MARKED to val. */
static void
mark_or_check_tags (tree t, tree *tp, abi_tag_data *p, bool val)
{
while (t != global_namespace)
{
tree attr;
if (TYPE_P (t))
{
attr = TYPE_ATTRIBUTES (t);
t = CP_TYPE_CONTEXT (t);
}
else
{
attr = DECL_ATTRIBUTES (t);
t = CP_DECL_CONTEXT (t);
}
mark_or_check_attr_tags (attr, tp, p, val);
}
}
/* walk_tree callback for check_abi_tags: if the type at *TP involves any
types with abi tags, add the corresponding identifiers to the VEC in
types with ABI tags, add the corresponding identifiers to the VEC in
*DATA and set IDENTIFIER_MARKED. */
static tree
@ -1447,63 +1501,112 @@ find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
for (tree ns = decl_namespace_context (*tp);
ns != global_namespace;
ns = CP_DECL_CONTEXT (ns))
if (NAMESPACE_ABI_TAG (ns))
check_tag (DECL_NAME (ns), tp, p);
mark_or_check_tags (*tp, tp, p, false);
if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp)))
{
for (tree list = TREE_VALUE (attributes); list;
list = TREE_CHAIN (list))
{
tree tag = TREE_VALUE (list);
check_tag (tag, tp, p);
}
}
return NULL_TREE;
}
/* Set IDENTIFIER_MARKED on all the ABI tags on T and its (transitively
complete) template arguments. */
/* walk_tree callback for mark_abi_tags: if *TP is a class, set
IDENTIFIER_MARKED on its ABI tags. */
static tree
mark_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
{
if (!OVERLOAD_TYPE_P (*tp))
return NULL_TREE;
/* walk_tree shouldn't be walking into any subtrees of a RECORD_TYPE
anyway, but let's make sure of it. */
*walk_subtrees = false;
bool *valp = static_cast<bool*>(data);
mark_or_check_tags (*tp, NULL, NULL, *valp);
return NULL_TREE;
}
/* Set IDENTIFIER_MARKED on all the ABI tags on T and its enclosing
scopes. */
static void
mark_type_abi_tags (tree t, bool val)
mark_abi_tags (tree t, bool val)
{
for (tree ns = decl_namespace_context (t);
ns != global_namespace;
ns = CP_DECL_CONTEXT (ns))
if (NAMESPACE_ABI_TAG (ns))
IDENTIFIER_MARKED (DECL_NAME (ns)) = val;
tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
if (attributes)
mark_or_check_tags (t, NULL, NULL, val);
if (DECL_P (t))
{
for (tree list = TREE_VALUE (attributes); list;
list = TREE_CHAIN (list))
if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
{
tree tag = TREE_VALUE (list);
tree id = get_identifier (TREE_STRING_POINTER (tag));
IDENTIFIER_MARKED (id) = val;
/* Template arguments are part of the signature. */
tree level = INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (t));
for (int j = 0; j < TREE_VEC_LENGTH (level); ++j)
{
tree arg = TREE_VEC_ELT (level, j);
cp_walk_tree_without_duplicates (&arg, mark_abi_tags_r, &val);
}
}
if (TREE_CODE (t) == FUNCTION_DECL)
/* A function's parameter types are part of the signature, so
we don't need to inherit any tags that are also in them. */
for (tree arg = FUNCTION_FIRST_USER_PARMTYPE (t); arg;
arg = TREE_CHAIN (arg))
cp_walk_tree_without_duplicates (&TREE_VALUE (arg),
mark_abi_tags_r, &val);
}
}
/* Check that class T has all the abi tags that subobject SUBOB has, or
warn if not. */
/* Check that T has all the ABI tags that subobject SUBOB has, or
warn if not. If T is a (variable or function) declaration, also
add any missing tags. */
static void
check_abi_tags (tree t, tree subob)
{
mark_type_abi_tags (t, true);
bool inherit = DECL_P (t);
if (!inherit && !warn_abi_tag)
return;
tree decl = TYPE_P (t) ? TYPE_NAME (t) : t;
if (!TREE_PUBLIC (decl))
/* No need to worry about things local to this TU. */
return;
mark_abi_tags (t, true);
tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob);
struct abi_tag_data data = { t, subob, error_mark_node };
if (inherit)
data.tags = NULL_TREE;
cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data);
mark_type_abi_tags (t, false);
if (inherit && data.tags)
{
tree attr = lookup_attribute ("abi_tag", DECL_ATTRIBUTES (t));
if (attr)
TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr));
else
DECL_ATTRIBUTES (t)
= tree_cons (get_identifier ("abi_tag"), data.tags,
DECL_ATTRIBUTES (t));
}
mark_abi_tags (t, false);
}
/* Check that DECL has all the ABI tags that are used in parts of its type
that are not reflected in its mangled name. */
void
check_abi_tags (tree decl)
{
if (TREE_CODE (decl) == VAR_DECL)
check_abi_tags (decl, TREE_TYPE (decl));
else if (TREE_CODE (decl) == FUNCTION_DECL
&& !mangle_return_type_p (decl))
check_abi_tags (decl, TREE_TYPE (TREE_TYPE (decl)));
}
void
@ -1513,7 +1616,7 @@ inherit_targ_abi_tags (tree t)
|| CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
return;
mark_type_abi_tags (t, true);
mark_abi_tags (t, true);
tree args = CLASSTYPE_TI_ARGS (t);
struct abi_tag_data data = { t, NULL_TREE, NULL_TREE };
@ -1541,7 +1644,7 @@ inherit_targ_abi_tags (tree t)
TYPE_ATTRIBUTES (t));
}
mark_type_abi_tags (t, false);
mark_abi_tags (t, false);
}
/* Return true, iff class T has a non-virtual destructor that is

View File

@ -152,7 +152,7 @@ c-common.h, not after.
DECL_MUTABLE_P (in FIELD_DECL)
DECL_DEPENDENT_P (in USING_DECL)
LABEL_DECL_BREAK (in LABEL_DECL)
NAMESPACE_ABI_TAG (in NAMESPACE_DECL)
NAMESPACE_IS_INLINE (in NAMESPACE_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
@ -2657,9 +2657,8 @@ struct GTY(()) lang_decl {
#define LOCAL_CLASS_P(NODE) \
(decl_function_context (TYPE_MAIN_DECL (NODE)) != NULL_TREE)
/* 1 iff this NAMESPACE_DECL should also be treated as an ABI tag for
-Wabi-tag. */
#define NAMESPACE_ABI_TAG(NODE) \
/* 1 iff this NAMESPACE_DECL is an inline namespace. */
#define NAMESPACE_IS_INLINE(NODE) \
DECL_LANG_FLAG_0 (NAMESPACE_DECL_CHECK (NODE))
/* For a NAMESPACE_DECL: the list of using namespace directives
@ -5311,6 +5310,7 @@ extern void explain_non_literal_class (tree);
extern void inherit_targ_abi_tags (tree);
extern void defaulted_late_check (tree);
extern bool defaultable_fn_check (tree);
extern void check_abi_tags (tree);
extern void fixup_type_variants (tree);
extern void fixup_attribute_variants (tree);
extern tree* decl_cloned_function_p (const_tree, bool);
@ -6069,6 +6069,7 @@ extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern bool check_abi_tag_redeclaration (const_tree, const_tree, const_tree);
extern bool check_abi_tag_args (tree, tree);
extern tree strip_typedefs (tree);
extern tree strip_typedefs_expr (tree);
extern tree copy_binfo (tree, tree, tree,
@ -6345,6 +6346,7 @@ extern tree mangle_tls_wrapper_fn (tree);
extern bool decl_tls_wrapper_p (tree);
extern tree mangle_ref_init_variable (tree);
extern char * get_mangled_vtable_map_var_name (tree);
extern bool mangle_return_type_p (tree);
/* in dump.c */
extern bool cp_dump_tree (void *, tree);

View File

@ -648,6 +648,48 @@ find_substitution (tree node)
return 1;
}
/* Returns whether DECL's symbol name should be the plain unqualified-id
rather than a more complicated mangled name. */
static bool
unmangled_name_p (const tree decl)
{
if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* The names of `extern "C"' functions are not mangled. */
return (DECL_EXTERN_C_FUNCTION_P (decl)
/* But overloaded operator names *are* mangled. */
&& !DECL_OVERLOADED_OPERATOR_P (decl));
}
else if (VAR_P (decl))
{
/* static variables are mangled. */
if (!DECL_EXTERNAL_LINKAGE_P (decl))
return false;
/* extern "C" declarations aren't mangled. */
if (DECL_EXTERN_C_P (decl))
return true;
/* Other variables at non-global scope are mangled. */
if (CP_DECL_CONTEXT (decl) != global_namespace)
return false;
/* Variable template instantiations are mangled. */
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& variable_template_p (DECL_TI_TEMPLATE (decl)))
return false;
/* Declarations with ABI tags are mangled. */
if (lookup_attribute ("abi_tag", DECL_ATTRIBUTES (decl)))
return false;
/* The names of non-static global variables aren't mangled. */
return true;
}
return false;
}
/* TOP_LEVEL is true, if this is being called at outermost level of
mangling. It should be false when mangling a decl appearing in an
@ -660,13 +702,10 @@ write_mangled_name (const tree decl, bool top_level)
{
MANGLE_TRACE_TREE ("mangled-name", decl);
if (/* The names of `extern "C"' functions are not mangled. */
DECL_EXTERN_C_FUNCTION_P (decl)
/* But overloaded operator names *are* mangled. */
&& !DECL_OVERLOADED_OPERATOR_P (decl))
{
unmangled_name:;
check_abi_tags (decl);
if (unmangled_name_p (decl))
{
if (top_level)
write_string (IDENTIFIER_POINTER (DECL_NAME (decl)));
else
@ -680,18 +719,6 @@ write_mangled_name (const tree decl, bool top_level)
write_source_name (DECL_NAME (decl));
}
}
else if (VAR_P (decl)
/* Variable template instantiations are mangled. */
&& !(DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& variable_template_p (DECL_TI_TEMPLATE (decl)))
/* The names of non-static global variables aren't mangled. */
&& DECL_EXTERNAL_LINKAGE_P (decl)
&& (CP_DECL_CONTEXT (decl) == global_namespace
/* And neither are `extern "C"' variables. */
|| DECL_EXTERN_C_P (decl)))
{
goto unmangled_name;
}
else
{
write_string ("_Z");
@ -699,6 +726,18 @@ write_mangled_name (const tree decl, bool top_level)
}
}
/* Returns true if the return type of DECL is part of its signature, and
therefore its mangling. */
bool
mangle_return_type_p (tree decl)
{
return (!DECL_CONSTRUCTOR_P (decl)
&& !DECL_DESTRUCTOR_P (decl)
&& !DECL_CONV_FN_P (decl)
&& decl_is_template_id (decl, NULL));
}
/* <encoding> ::= <function name> <bare-function-type>
::= <data name> */
@ -740,10 +779,7 @@ write_encoding (const tree decl)
}
write_bare_function_type (fn_type,
(!DECL_CONSTRUCTOR_P (decl)
&& !DECL_DESTRUCTOR_P (decl)
&& !DECL_CONV_FN_P (decl)
&& decl_is_template_id (decl, NULL)),
mangle_return_type_p (decl),
d);
}
}
@ -1290,7 +1326,7 @@ write_unqualified_name (tree decl)
if (tree tmpl = most_general_template (decl))
decl = DECL_TEMPLATE_RESULT (tmpl);
/* Don't crash on an unbound class template. */
if (decl)
if (decl && TREE_CODE (decl) != NAMESPACE_DECL)
{
tree attrs = (TREE_CODE (decl) == TYPE_DECL
? TYPE_ATTRIBUTES (TREE_TYPE (decl))

View File

@ -3657,7 +3657,24 @@ handle_namespace_attrs (tree ns, tree attributes)
}
else if (is_attribute_p ("abi_tag", name))
{
NAMESPACE_ABI_TAG (ns) = true;
if (!NAMESPACE_IS_INLINE (ns))
{
warning (OPT_Wattributes, "ignoring %qD attribute on non-inline "
"namespace", name);
continue;
}
if (!args)
{
tree dn = DECL_NAME (ns);
args = build_string (IDENTIFIER_LENGTH (dn) + 1,
IDENTIFIER_POINTER (dn));
TREE_TYPE (args) = char_array_type_node;
args = fix_string_type (args);
args = build_tree_list (NULL_TREE, args);
}
if (check_abi_tag_args (args, name))
DECL_ATTRIBUTES (ns) = tree_cons (name, args,
DECL_ATTRIBUTES (ns));
}
else
{

View File

@ -16233,6 +16233,7 @@ cp_parser_namespace_definition (cp_parser* parser)
if (is_inline)
{
tree name_space = current_namespace;
NAMESPACE_IS_INLINE (name_space) = true;
/* Set up namespace association. */
DECL_NAMESPACE_ASSOCIATIONS (name_space)
= tree_cons (CP_DECL_CONTEXT (name_space), NULL_TREE,

View File

@ -3485,13 +3485,17 @@ check_abi_tag_redeclaration (const_tree decl, const_tree old, const_tree new_)
return true;
}
/* Handle an "abi_tag" attribute; arguments as in
struct attribute_spec.handler. */
/* The abi_tag attribute with the name NAME was given ARGS. If they are
ill-formed, give an error and return false; otherwise, return true. */
static tree
handle_abi_tag_attribute (tree* node, tree name, tree args,
int flags, bool* no_add_attrs)
bool
check_abi_tag_args (tree args, tree name)
{
if (!args)
{
error ("the %qE attribute requires arguments", name);
return false;
}
for (tree arg = args; arg; arg = TREE_CHAIN (arg))
{
tree elt = TREE_VALUE (arg);
@ -3502,7 +3506,7 @@ handle_abi_tag_attribute (tree* node, tree name, tree args,
{
error ("arguments to the %qE attribute must be narrow string "
"literals", name);
goto fail;
return false;
}
const char *begin = TREE_STRING_POINTER (elt);
const char *end = begin + TREE_STRING_LENGTH (elt);
@ -3517,7 +3521,7 @@ handle_abi_tag_attribute (tree* node, tree name, tree args,
"identifiers", name);
inform (input_location, "%<%c%> is not a valid first "
"character for an identifier", c);
goto fail;
return false;
}
}
else if (p == end - 1)
@ -3530,11 +3534,23 @@ handle_abi_tag_attribute (tree* node, tree name, tree args,
"identifiers", name);
inform (input_location, "%<%c%> is not a valid character "
"in an identifier", c);
goto fail;
return false;
}
}
}
}
return true;
}
/* Handle an "abi_tag" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_abi_tag_attribute (tree* node, tree name, tree args,
int flags, bool* no_add_attrs)
{
if (!check_abi_tag_args (args, name))
goto fail;
if (TYPE_P (*node))
{
@ -3578,14 +3594,16 @@ handle_abi_tag_attribute (tree* node, tree name, tree args,
}
else
{
if (TREE_CODE (*node) != FUNCTION_DECL)
if (TREE_CODE (*node) != FUNCTION_DECL
&& TREE_CODE (*node) != VAR_DECL)
{
error ("%qE attribute applied to non-function %qD", name, *node);
error ("%qE attribute applied to non-function, non-variable %qD",
name, *node);
goto fail;
}
else if (DECL_LANGUAGE (*node) == lang_c)
{
error ("%qE attribute applied to extern \"C\" function %qD",
error ("%qE attribute applied to extern \"C\" declaration %qD",
name, *node);
goto fail;
}

View File

@ -18722,18 +18722,26 @@ Some attributes only make sense for C++ programs.
@table @code
@item abi_tag ("@var{tag}", ...)
@cindex @code{abi_tag} attribute
The @code{abi_tag} attribute can be applied to a function or class
declaration. It modifies the mangled name of the function or class to
The @code{abi_tag} attribute can be applied to a function, variable, or class
declaration. It modifies the mangled name of the entity to
incorporate the tag name, in order to distinguish the function or
class from an earlier version with a different ABI; perhaps the class
has changed size, or the function has a different return type that is
not encoded in the mangled name.
The attribute can also be applied to an inline namespace, but does not
affect the mangled name of the namespace; in this case it is only used
for @option{-Wabi-tag} warnings and automatic tagging of functions and
variables. Tagging inline namespaces is generally preferable to
tagging individual declarations, but the latter is sometimes
necessary, such as when only certain members of a class need to be
tagged.
The argument can be a list of strings of arbitrary length. The
strings are sorted on output, so the order of the list is
unimportant.
A redeclaration of a function or class must not add new ABI tags,
A redeclaration of an entity must not add new ABI tags,
since doing so would change the mangled name.
The ABI tags apply to a name, so all instantiations and
@ -18745,6 +18753,13 @@ not have all the ABI tags used by its subobjects and virtual functions; for user
that needs to coexist with an earlier ABI, using this option can help
to find all affected types that need to be tagged.
When a type involving an ABI tag is used as the type of a variable or
return type of a function where that tag is not already present in the
signature of the function, the tag is automatically applied to the
variable or function. @option{-Wabi-tag} also warns about this
situation; this warning can be avoided by explicitly tagging the
variable or function or moving it into a tagged inline namespace.
@item init_priority (@var{priority})
@cindex @code{init_priority} attribute

View File

@ -197,7 +197,7 @@ in the following sections.
-fvtv-counts -fvtv-debug @gol
-fvisibility-ms-compat @gol
-fext-numeric-literals @gol
-Wabi=@var{n} -Wconversion-null -Wctor-dtor-privacy @gol
-Wabi=@var{n} -Wabi-tag -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
@ -2641,6 +2641,13 @@ union U @{
@end itemize
@item -Wabi-tag @r{(C++ and Objective-C++ only)}
@opindex Wabi-tag
@opindex -Wabi-tag
Warn when a type with an ABI tag is used in a context that does not
have that ABI tag. See @ref{C++ Attributes} for more information
about ABI tags.
@item -Wctor-dtor-privacy @r{(C++ and Objective-C++ only)}
@opindex Wctor-dtor-privacy
@opindex Wno-ctor-dtor-privacy

View File

@ -5,8 +5,8 @@ void f(int) __attribute ((abi_tag ("foo","bar")));
struct __attribute ((abi_tag ("bar"))) A { };
struct B: A { }; // { dg-warning "bar. abi tag" }
struct D { A* ap; }; // { dg-warning "bar. abi tag" }
struct B: A { }; // { dg-warning "bar. ABI tag" }
struct D { A* ap; }; // { dg-warning "bar. ABI tag" }
// { dg-final { scan-assembler "_Z1gB3baz1AB3bar" } }
void g(A) __attribute ((abi_tag ("baz")));

View File

@ -0,0 +1,30 @@
// { dg-options "-Wabi-tag" }
inline namespace __cxx11 __attribute ((abi_tag ("cxx11"))) {
struct A {};
};
// { dg-final { scan-assembler "_Z1aB5cxx11" } }
A a; // { dg-warning "\"cxx11\"" }
// { dg-final { scan-assembler "_Z1fB5cxx11v" } }
A f() {} // { dg-warning "\"cxx11\"" }
namespace {
A a2;
A f2() {}
struct B: A {};
}
// { dg-final { scan-assembler "_Z1fPN7__cxx111AE" } }
A f(A*) {}
// { dg-final { scan-assembler "_Z1gIN7__cxx111AEET_v" } }
template <class T> T g() { }
template <> A g<A>() { }
// { dg-final { scan-assembler "_Z1vIN7__cxx111AEE" { target c++14 } } }
#if __cplusplus >= 201402L
template <class T> T v = T();
void *p = &v<A>;
#endif

View File

@ -2,7 +2,7 @@
struct __attribute ((abi_tag ("X"))) A { };
struct B // { dg-warning "abi tag" }
struct B // { dg-warning "ABI tag" }
{
virtual void f(A); // { dg-message "declared here" }
};

View File

@ -4,6 +4,6 @@ template<class T>
struct __attribute ((__abi_tag__("cxx11"))) list // { dg-message "list" }
{ };
struct X { // { dg-warning "abi tag" }
struct X { // { dg-warning "ABI tag" }
list<int> l; // { dg-message "X::l" }
};

View File

@ -1,3 +1,8 @@
2015-03-19 Jason Merrill <jason@redhat.com>
* config/locale/gnu/messages_members.cc: Revert abi-tag change.
* src/c++11/cxx11-shim_facets.cc: Revert abi-tag change.
2015-03-18 Jonathan Wakely <jwakely@redhat.com>
PR c++/65046

View File

@ -46,8 +46,8 @@ namespace
typedef messages_base::catalog catalog;
struct _GLIBCXX_DEFAULT_ABI_TAG Catalog_info
{
struct Catalog_info
{
Catalog_info(catalog __id, const string& __domain, locale __loc)
: _M_id(__id), _M_domain(__domain), _M_locale(__loc)
{ }
@ -57,7 +57,7 @@ namespace
locale _M_locale;
};
class _GLIBCXX_DEFAULT_ABI_TAG Catalogs
class Catalogs
{
public:
Catalogs() : _M_catalog_counter(0) { }
@ -133,7 +133,6 @@ namespace
std::vector<Catalog_info*> _M_infos;
};
_GLIBCXX_DEFAULT_ABI_TAG
Catalogs&
get_catalogs()
{

View File

@ -215,7 +215,7 @@ namespace std
#if _GLIBCXX_USE_CXX11_ABI
namespace std
{
inline namespace __cxx11 __attribute__((__abi_tag__)) { }
inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { }
}
# define _GLIBCXX_NAMESPACE_CXX11 __cxx11::
# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 namespace __cxx11 {

View File

@ -227,8 +227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace // unnamed
{
template<typename _CharT>
struct _GLIBCXX_DEFAULT_ABI_TAG numpunct_shim
: std::numpunct<_CharT>, facet::__shim
struct numpunct_shim : std::numpunct<_CharT>, facet::__shim
{
typedef typename numpunct<_CharT>::__cache_type __cache_type;
@ -252,8 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _CharT>
struct _GLIBCXX_DEFAULT_ABI_TAG collate_shim
: std::collate<_CharT>, facet::__shim
struct collate_shim : std::collate<_CharT>, facet::__shim
{
typedef basic_string<_CharT> string_type;
@ -278,8 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _CharT>
struct _GLIBCXX_DEFAULT_ABI_TAG time_get_shim
: std::time_get<_CharT>, facet::__shim
struct time_get_shim : std::time_get<_CharT>, facet::__shim
{
typedef typename std::time_get<_CharT>::iter_type iter_type;
typedef typename std::time_get<_CharT>::char_type char_type;
@ -333,8 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _CharT, bool _Intl>
struct _GLIBCXX_DEFAULT_ABI_TAG moneypunct_shim
: std::moneypunct<_CharT, _Intl>, facet::__shim
struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, facet::__shim
{
typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
@ -361,8 +357,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _CharT>
struct _GLIBCXX_DEFAULT_ABI_TAG money_get_shim
: std::money_get<_CharT>, facet::__shim
struct money_get_shim : std::money_get<_CharT>, facet::__shim
{
typedef typename std::money_get<_CharT>::iter_type iter_type;
typedef typename std::money_get<_CharT>::char_type char_type;
@ -403,8 +398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _CharT>
struct _GLIBCXX_DEFAULT_ABI_TAG money_put_shim
: std::money_put<_CharT>, facet::__shim
struct money_put_shim : std::money_put<_CharT>, facet::__shim
{
typedef typename std::money_put<_CharT>::iter_type iter_type;
typedef typename std::money_put<_CharT>::char_type char_type;
@ -433,8 +427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
template<typename _CharT>
struct _GLIBCXX_DEFAULT_ABI_TAG messages_shim
: std::messages<_CharT>, facet::__shim
struct messages_shim : std::messages<_CharT>, facet::__shim
{
typedef messages_base::catalog catalog;
typedef basic_string<_CharT> string_type;