aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-04-01 13:49:38 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-04-01 13:49:38 -0400
commit2982147e0fd2dd4c280b7b68a5b1d784a7a077b1 (patch)
treec54130f7a2a0a694cfbc8ec485ff5ca05b1525c4 /gcc
parent2bcbca7e7c8f6e1c750d23134af9706fce360dd5 (diff)
downloadgcc-2982147e0fd2dd4c280b7b68a5b1d784a7a077b1.zip
gcc-2982147e0fd2dd4c280b7b68a5b1d784a7a077b1.tar.gz
gcc-2982147e0fd2dd4c280b7b68a5b1d784a7a077b1.tar.bz2
re PR c++/60642 (Unclear diagnostic with invalid use of abi_tag attribute on explicit instantiation)
PR c++/60642 * decl2.c (is_late_template_attribute): Don't defer abi_tag. * mangle.c (write_unqualified_name): Fix abi_tag on templates. * pt.c (get_template_info): Handle NAMESPACE_DECL. (most_general_template): Handle more kinds of template. * tree.c (handle_abi_tag_attribute): Ignore abi_tag on template instantiations and specializations. From-SVN: r208992
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/cp/mangle.c23
-rw-r--r--gcc/cp/pt.c22
-rw-r--r--gcc/cp/tree.c12
-rw-r--r--gcc/doc/extend.texi4
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag3.C7
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag6.C25
-rw-r--r--gcc/testsuite/g++.dg/abi/abi-tag7.C9
9 files changed, 93 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 553a059..72e28aa 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2014-04-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/60642
+ * decl2.c (is_late_template_attribute): Don't defer abi_tag.
+ * mangle.c (write_unqualified_name): Fix abi_tag on templates.
+ * pt.c (get_template_info): Handle NAMESPACE_DECL.
+ (most_general_template): Handle more kinds of template.
+ * tree.c (handle_abi_tag_attribute): Ignore abi_tag on template
+ instantiations and specializations.
+
2014-03-31 Patrick Palka patrick@parcs.ath.cx
PR c++/44859
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index dfc532d..6c52e53 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1169,8 +1169,9 @@ is_late_template_attribute (tree attr, tree decl)
/* Also defer most attributes on dependent types. This is not
necessary in all cases, but is the better default. */
else if (dependent_type_p (type)
- /* But attribute visibility specifically works on
- templates. */
+ /* But attributes abi_tag and visibility specifically apply
+ to templates. */
+ && !is_attribute_p ("abi_tag", name)
&& !is_attribute_p ("visibility", name))
return true;
else
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 251edb1..da82dd6 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -180,7 +180,7 @@ static void write_unscoped_template_name (const tree);
static void write_nested_name (const tree);
static void write_prefix (const tree);
static void write_template_prefix (const tree);
-static void write_unqualified_name (const tree);
+static void write_unqualified_name (tree);
static void write_conversion_operator_name (const tree);
static void write_source_name (tree);
static void write_literal_operator_name (tree);
@@ -1195,7 +1195,7 @@ write_unqualified_id (tree identifier)
}
static void
-write_unqualified_name (const tree decl)
+write_unqualified_name (tree decl)
{
MANGLE_TRACE_TREE ("unqualified-name", decl);
@@ -1280,10 +1280,21 @@ write_unqualified_name (const tree decl)
write_source_name (DECL_NAME (decl));
}
- tree attrs = (TREE_CODE (decl) == TYPE_DECL
- ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
- : DECL_ATTRIBUTES (decl));
- write_abi_tags (lookup_attribute ("abi_tag", attrs));
+ /* We use the ABI tags from the primary template, ignoring tags on any
+ specializations. This is necessary because C++ doesn't require a
+ specialization to be declared before it is used unless the use
+ requires a complete type, but we need to get the tags right on
+ incomplete types as well. */
+ if (tree tmpl = most_general_template (decl))
+ decl = DECL_TEMPLATE_RESULT (tmpl);
+ /* Don't crash on an unbound class template. */
+ if (decl)
+ {
+ tree attrs = (TREE_CODE (decl) == TYPE_DECL
+ ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+ : DECL_ATTRIBUTES (decl));
+ write_abi_tags (lookup_attribute ("abi_tag", attrs));
+ }
}
/* Write the unqualified-name for a conversion operator to TYPE. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c791d03..bfb49d7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -320,6 +320,9 @@ get_template_info (const_tree t)
if (!t || t == error_mark_node)
return NULL;
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ return NULL;
+
if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
tinfo = DECL_TEMPLATE_INFO (t);
@@ -18758,23 +18761,18 @@ most_specialized_instantiation (tree templates)
tree
most_general_template (tree decl)
{
- /* If DECL is a FUNCTION_DECL, find the TEMPLATE_DECL of which it is
- an immediate specialization. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TREE_CODE (decl) != TEMPLATE_DECL)
{
- if (DECL_TEMPLATE_INFO (decl)) {
- decl = DECL_TI_TEMPLATE (decl);
-
- /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE for a
- template friend. */
- if (TREE_CODE (decl) != TEMPLATE_DECL)
- return NULL_TREE;
- } else
+ if (tree tinfo = get_template_info (decl))
+ decl = TI_TEMPLATE (tinfo);
+ /* The TI_TEMPLATE can be an IDENTIFIER_NODE for a
+ template friend, or a FIELD_DECL for a capture pack. */
+ if (TREE_CODE (decl) != TEMPLATE_DECL)
return NULL_TREE;
}
/* Look for more and more general templates. */
- while (DECL_TEMPLATE_INFO (decl))
+ while (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
{
/* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE in some cases.
(See cp-tree.h for details.) */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 5567253..3429d23 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -3364,6 +3364,18 @@ handle_abi_tag_attribute (tree* node, tree name, tree args,
name, *node);
goto fail;
}
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (*node))
+ {
+ warning (OPT_Wattributes, "ignoring %qE attribute applied to "
+ "template instantiation %qT", name, *node);
+ goto fail;
+ }
+ else if (CLASSTYPE_TEMPLATE_SPECIALIZATION (*node))
+ {
+ warning (OPT_Wattributes, "ignoring %qE attribute applied to "
+ "template specialization %qT", name, *node);
+ goto fail;
+ }
tree attributes = TYPE_ATTRIBUTES (*node);
tree decl = TYPE_NAME (*node);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f9114ab..2c84e40 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -17542,6 +17542,10 @@ unimportant.
A redeclaration of a function or class 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
+specializations of a template have the same tags. The attribute will
+be ignored if applied to an explicit specialization or instantiation.
+
The @option{-Wabi-tag} flag enables a warning about a class which does
not have all the ABI tags used by its subobjects and virtual functions; for users with code
that needs to coexist with an earlier ABI, using this option can help
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag3.C b/gcc/testsuite/g++.dg/abi/abi-tag3.C
index 05fd58e..13cb3c2 100644
--- a/gcc/testsuite/g++.dg/abi/abi-tag3.C
+++ b/gcc/testsuite/g++.dg/abi/abi-tag3.C
@@ -1,5 +1,4 @@
-// An explicit specialization doesn't get the tag from its template unless
-// it is specified there, too.
+// An explicit specialization gets the tag from its template.
// { dg-final { scan-assembler "_ZN3FooB5cxx11IcE1fEv" } }
template<typename T>
@@ -12,12 +11,12 @@ struct __attribute ((abi_tag("cxx11"))) Foo
template<>
struct
__attribute ((abi_tag("cxx11")))
-Foo<int>
+Foo<int> // { dg-warning "attribute" }
{
int f();
};
-// { dg-final { scan-assembler "_ZN3FooIdE1fEv" } }
+// { dg-final { scan-assembler "_ZN3FooB5cxx11IdE1fEv" } }
template<>
struct
Foo<double>
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag6.C b/gcc/testsuite/g++.dg/abi/abi-tag6.C
new file mode 100644
index 0000000..94ea2f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag6.C
@@ -0,0 +1,25 @@
+// PR c++/60642
+
+struct __attribute((abi_tag("test"))) foo
+{
+ void f();
+ virtual ~foo();
+};
+
+template<typename>
+struct __attribute((abi_tag("test"))) bar
+{
+ void f();
+ virtual ~bar();
+};
+
+int main()
+{
+ foo f;
+ f.f();
+
+ bar<int> b;
+ b.f();
+}
+
+// { dg-final { scan-assembler "_ZTV3barB4testIiE" } }
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag7.C b/gcc/testsuite/g++.dg/abi/abi-tag7.C
new file mode 100644
index 0000000..4c47725
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag7.C
@@ -0,0 +1,9 @@
+// PR c++/60642
+
+template<typename T>
+class __attribute((abi_tag("foo"))) test{ };
+
+template class __attribute((abi_tag("foo"))) test<int>; // { dg-warning "attribute" }
+
+void f(test<char>*) {}
+// { dg-final { scan-assembler "_Z1fP4testB3fooIcE" } }