Commit 2982147e by Jason Merrill Committed by Jason Merrill

re PR c++/60642 (Unclear diagnostic with invalid use of abi_tag attribute on…

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
parent 2bcbca7e
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 2014-03-31 Patrick Palka patrick@parcs.ath.cx
PR c++/44859 PR c++/44859
......
...@@ -1169,8 +1169,9 @@ is_late_template_attribute (tree attr, tree decl) ...@@ -1169,8 +1169,9 @@ is_late_template_attribute (tree attr, tree decl)
/* Also defer most attributes on dependent types. This is not /* Also defer most attributes on dependent types. This is not
necessary in all cases, but is the better default. */ necessary in all cases, but is the better default. */
else if (dependent_type_p (type) else if (dependent_type_p (type)
/* But attribute visibility specifically works on /* But attributes abi_tag and visibility specifically apply
templates. */ to templates. */
&& !is_attribute_p ("abi_tag", name)
&& !is_attribute_p ("visibility", name)) && !is_attribute_p ("visibility", name))
return true; return true;
else else
......
...@@ -180,7 +180,7 @@ static void write_unscoped_template_name (const tree); ...@@ -180,7 +180,7 @@ static void write_unscoped_template_name (const tree);
static void write_nested_name (const tree); static void write_nested_name (const tree);
static void write_prefix (const tree); static void write_prefix (const tree);
static void write_template_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_conversion_operator_name (const tree);
static void write_source_name (tree); static void write_source_name (tree);
static void write_literal_operator_name (tree); static void write_literal_operator_name (tree);
...@@ -1195,7 +1195,7 @@ write_unqualified_id (tree identifier) ...@@ -1195,7 +1195,7 @@ write_unqualified_id (tree identifier)
} }
static void static void
write_unqualified_name (const tree decl) write_unqualified_name (tree decl)
{ {
MANGLE_TRACE_TREE ("unqualified-name", decl); MANGLE_TRACE_TREE ("unqualified-name", decl);
...@@ -1280,10 +1280,21 @@ write_unqualified_name (const tree decl) ...@@ -1280,10 +1280,21 @@ write_unqualified_name (const tree decl)
write_source_name (DECL_NAME (decl)); write_source_name (DECL_NAME (decl));
} }
tree attrs = (TREE_CODE (decl) == TYPE_DECL /* We use the ABI tags from the primary template, ignoring tags on any
? TYPE_ATTRIBUTES (TREE_TYPE (decl)) specializations. This is necessary because C++ doesn't require a
: DECL_ATTRIBUTES (decl)); specialization to be declared before it is used unless the use
write_abi_tags (lookup_attribute ("abi_tag", attrs)); 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. */ /* Write the unqualified-name for a conversion operator to TYPE. */
......
...@@ -320,6 +320,9 @@ get_template_info (const_tree t) ...@@ -320,6 +320,9 @@ get_template_info (const_tree t)
if (!t || t == error_mark_node) if (!t || t == error_mark_node)
return NULL; return NULL;
if (TREE_CODE (t) == NAMESPACE_DECL)
return NULL;
if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
tinfo = DECL_TEMPLATE_INFO (t); tinfo = DECL_TEMPLATE_INFO (t);
...@@ -18758,23 +18761,18 @@ most_specialized_instantiation (tree templates) ...@@ -18758,23 +18761,18 @@ most_specialized_instantiation (tree templates)
tree tree
most_general_template (tree decl) most_general_template (tree decl)
{ {
/* If DECL is a FUNCTION_DECL, find the TEMPLATE_DECL of which it is if (TREE_CODE (decl) != TEMPLATE_DECL)
an immediate specialization. */
if (TREE_CODE (decl) == FUNCTION_DECL)
{ {
if (DECL_TEMPLATE_INFO (decl)) { if (tree tinfo = get_template_info (decl))
decl = DECL_TI_TEMPLATE (decl); decl = TI_TEMPLATE (tinfo);
/* The TI_TEMPLATE can be an IDENTIFIER_NODE for a
/* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE for a template friend, or a FIELD_DECL for a capture pack. */
template friend. */ if (TREE_CODE (decl) != TEMPLATE_DECL)
if (TREE_CODE (decl) != TEMPLATE_DECL)
return NULL_TREE;
} else
return NULL_TREE; return NULL_TREE;
} }
/* Look for more and more general templates. */ /* 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. /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE in some cases.
(See cp-tree.h for details.) */ (See cp-tree.h for details.) */
......
...@@ -3364,6 +3364,18 @@ handle_abi_tag_attribute (tree* node, tree name, tree args, ...@@ -3364,6 +3364,18 @@ handle_abi_tag_attribute (tree* node, tree name, tree args,
name, *node); name, *node);
goto fail; 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 attributes = TYPE_ATTRIBUTES (*node);
tree decl = TYPE_NAME (*node); tree decl = TYPE_NAME (*node);
......
...@@ -17542,6 +17542,10 @@ unimportant. ...@@ -17542,6 +17542,10 @@ unimportant.
A redeclaration of a function or class must not add new ABI tags, A redeclaration of a function or class must not add new ABI tags,
since doing so would change the mangled name. 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 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 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 that needs to coexist with an earlier ABI, using this option can help
......
// An explicit specialization doesn't get the tag from its template unless // An explicit specialization gets the tag from its template.
// it is specified there, too.
// { dg-final { scan-assembler "_ZN3FooB5cxx11IcE1fEv" } } // { dg-final { scan-assembler "_ZN3FooB5cxx11IcE1fEv" } }
template<typename T> template<typename T>
...@@ -12,12 +11,12 @@ struct __attribute ((abi_tag("cxx11"))) Foo ...@@ -12,12 +11,12 @@ struct __attribute ((abi_tag("cxx11"))) Foo
template<> template<>
struct struct
__attribute ((abi_tag("cxx11"))) __attribute ((abi_tag("cxx11")))
Foo<int> Foo<int> // { dg-warning "attribute" }
{ {
int f(); int f();
}; };
// { dg-final { scan-assembler "_ZN3FooIdE1fEv" } } // { dg-final { scan-assembler "_ZN3FooB5cxx11IdE1fEv" } }
template<> template<>
struct struct
Foo<double> Foo<double>
......
// 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" } }
// 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" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment