summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2015-03-10 15:34:49 -0400
committerJason Merrill <jason@redhat.com>2015-03-13 14:05:23 -0400
commit82ea96a59b2d4594fcbfa1894af26878187e2e8c (patch)
tree60d333cb5a602623fd3e20b81035e3798114c80c
parent9dba8b1d24c82b3347b13eb5f19396c5ecd49988 (diff)
downloadgcc-jason/tag-inherit.tar.gz
* class.c (check_tag): Handle variables and functions.jason/tag-inherit
(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.
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/class.c172
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/mangle.c82
-rw-r--r--gcc/cp/name-lookup.c19
-rw-r--r--gcc/cp/parser.c1
-rw-r--r--gcc/cp/tree.c40
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag1.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag14.C11
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag4.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag8.C2
-rw-r--r--libstdc++-v3/include/bits/c++config2
12 files changed, 262 insertions, 102 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 259ce9c9839..c66de3f4e1d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,22 @@
+2015-03-13 Jason Merrill <jason@redhat.com>
+
+ * 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-12 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/65323
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 8612163711c..c3dd9b418dd 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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,65 @@ 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. */
+/* 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)
- {
- for (tree list = TREE_VALUE (attributes); list;
- list = TREE_CHAIN (list))
- {
- tree tag = TREE_VALUE (list);
- tree id = get_identifier (TREE_STRING_POINTER (tag));
- IDENTIFIER_MARKED (id) = val;
- }
- }
+ mark_or_check_tags (t, NULL, NULL, val);
}
-/* Check that class T has all the abi tags that subobject SUBOB has, or
+/* Check that class T has all the ABI tags that subobject SUBOB has, or
warn if not. */
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;
+
+ 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 +1569,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 +1597,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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 65219f159e3..7111449da4b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index fbf4bf27c07..b0f72d1ff14 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index ba16befa74d..c845d521a53 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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
{
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a209ee608fa..ac5ad9564a5 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16231,6 +16231,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,
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c8e6f0c796f..ef53aff87f7 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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;
}
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag1.C b/gcc/testsuite/g++.dg/abi/abi-tag1.C
index 942929cdd35..d57ed87d803 100644
--- a/gcc/testsuite/g++.dg/abi/abi-tag1.C
+++ b/gcc/testsuite/g++.dg/abi/abi-tag1.C
@@ -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")));
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag14.C b/gcc/testsuite/g++.dg/abi/abi-tag14.C
new file mode 100644
index 00000000000..65643bdcad7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag14.C
@@ -0,0 +1,11 @@
+// { 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\"" }
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag4.C b/gcc/testsuite/g++.dg/abi/abi-tag4.C
index 3f8d7bfbc3d..6bf4fa1c538 100644
--- a/gcc/testsuite/g++.dg/abi/abi-tag4.C
+++ b/gcc/testsuite/g++.dg/abi/abi-tag4.C
@@ -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" }
};
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag8.C b/gcc/testsuite/g++.dg/abi/abi-tag8.C
index 0a6eb5802af..7ead1cb86b4 100644
--- a/gcc/testsuite/g++.dg/abi/abi-tag8.C
+++ b/gcc/testsuite/g++.dg/abi/abi-tag8.C
@@ -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" }
};
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 46ffa1f5d0a..eebe34c604c 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -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 {