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
This commit is contained in:
parent
2bcbca7e7c
commit
2982147e0f
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
22
gcc/cp/pt.c
22
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.) */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" } }
|
|
@ -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" } }
|
Loading…
Reference in New Issue