diff mbox series

c++: abi_tag attribute on templates [PR109715]

Message ID 20231214191719.1941342-1-ppalka@redhat.com
State New
Headers show
Series c++: abi_tag attribute on templates [PR109715] | expand

Commit Message

Patrick Palka Dec. 14, 2023, 7:17 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  Do we want to condition this on abi_check (19)?

-- >8 --

As with other declaration attributes, we need to look through
TEMPLATE_DECL when looking up the abi_tag attribute.

	PR c++/109715

gcc/cp/ChangeLog:

	* mangle.cc (get_abi_tags): Look through TEMPLATE_DECL.

gcc/testsuite/ChangeLog:

	* g++.dg/abi/abi-tag25.C: New test.
---
 gcc/cp/mangle.cc                     |  3 +++
 gcc/testsuite/g++.dg/abi/abi-tag25.C | 17 +++++++++++++++++
 2 files changed, 20 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C

Comments

Jason Merrill Dec. 14, 2023, 8:33 p.m. UTC | #1
On 12/14/23 14:17, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?  Do we want to condition this on abi_check (19)?

I think we do, sadly.

> -- >8 --
> 
> As with other declaration attributes, we need to look through
> TEMPLATE_DECL when looking up the abi_tag attribute.
> 
> 	PR c++/109715
> 
> gcc/cp/ChangeLog:
> 
> 	* mangle.cc (get_abi_tags): Look through TEMPLATE_DECL.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/abi/abi-tag25.C: New test.
> ---
>   gcc/cp/mangle.cc                     |  3 +++
>   gcc/testsuite/g++.dg/abi/abi-tag25.C | 17 +++++++++++++++++
>   2 files changed, 20 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
> 
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index 0684f0e6038..1fbd879c116 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -527,6 +527,9 @@ get_abi_tags (tree t)
>     if (!t || TREE_CODE (t) == NAMESPACE_DECL)
>       return NULL_TREE;
>   
> +  if (TREE_CODE (t) == TEMPLATE_DECL && DECL_TEMPLATE_RESULT (t))
> +    t = DECL_TEMPLATE_RESULT (t);
> +
>     if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
>       t = TREE_TYPE (t);
>   
> diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25.C b/gcc/testsuite/g++.dg/abi/abi-tag25.C
> new file mode 100644
> index 00000000000..9847f0dccc8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/abi-tag25.C
> @@ -0,0 +1,17 @@
> +// PR c++/109715
> +// { dg-do compile { target c++11 } }
> +
> +template<class T>
> +[[gnu::abi_tag("foo")]] void fun() { }
> +
> +template void fun<int>();
> +
> +#if __cpp_variable_templates
> +template<class T>
> +[[gnu::abi_tag("foo")]] int var = 0;
> +
> +template int var<int>;
> +#endif
> +
> +// { dg-final { scan-assembler "_Z3funB3fooIiEvv" } }
> +// { dg-final { scan-assembler "_Z3varB3fooIiE" { target c++14 } } }
Patrick Palka Dec. 14, 2023, 9:08 p.m. UTC | #2
On Thu, 14 Dec 2023, Jason Merrill wrote:

> On 12/14/23 14:17, Patrick Palka wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > trunk?  Do we want to condition this on abi_check (19)?
> 
> I think we do, sadly.

Sounds good, like so?  Bootstrap and regtest in progress.

-- >8 --

Subject: [PATCH] c++: abi_tag attribute on templates [PR109715]

As with other declaration attributes, we need to look through
TEMPLATE_DECL when looking up the abi_tag attribute.

	PR c++/109715

gcc/cp/ChangeLog:

	* mangle.cc (get_abi_tags): Look through TEMPLATE_DECL.

gcc/testsuite/ChangeLog:

	* g++.dg/abi/abi-tag25.C: New test.
	* g++.dg/abi/abi-tag25a.C: New test.
---
 gcc/cp/mangle.cc                      |  6 ++++++
 gcc/testsuite/g++.dg/abi/abi-tag25.C  | 17 +++++++++++++++++
 gcc/testsuite/g++.dg/abi/abi-tag25a.C | 11 +++++++++++
 3 files changed, 34 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
 create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25a.C

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 0684f0e6038..e3383df1836 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -530,6 +530,12 @@ get_abi_tags (tree t)
   if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
     t = TREE_TYPE (t);
 
+  if (TREE_CODE (t) == TEMPLATE_DECL
+      && DECL_TEMPLATE_RESULT (t)
+      /* We used to ignore abi_tag on function and variable templates.  */
+      && abi_check (19))
+    t = DECL_TEMPLATE_RESULT (t);
+
   tree attrs;
   if (TYPE_P (t))
     attrs = TYPE_ATTRIBUTES (t);
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25.C b/gcc/testsuite/g++.dg/abi/abi-tag25.C
new file mode 100644
index 00000000000..9847f0dccc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag25.C
@@ -0,0 +1,17 @@
+// PR c++/109715
+// { dg-do compile { target c++11 } }
+
+template<class T>
+[[gnu::abi_tag("foo")]] void fun() { }
+
+template void fun<int>();
+
+#if __cpp_variable_templates
+template<class T>
+[[gnu::abi_tag("foo")]] int var = 0;
+
+template int var<int>;
+#endif
+
+// { dg-final { scan-assembler "_Z3funB3fooIiEvv" } }
+// { dg-final { scan-assembler "_Z3varB3fooIiE" { target c++14 } } }
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25a.C b/gcc/testsuite/g++.dg/abi/abi-tag25a.C
new file mode 100644
index 00000000000..9499b5614cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag25a.C
@@ -0,0 +1,11 @@
+// PR c++/109715
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fabi-version=18 -fabi-compat-version=18 -Wabi=0" }
+
+#include "abi-tag25.C"
+
+// { dg-warning "mangled name" "" { target *-*-* } 5 }
+// { dg-warning "mangled name" "" { target *-*-* } 11 }
+
+// { dg-final { scan-assembler "_Z3funIiEvv" } }
+// { dg-final { scan-assembler "_Z3varIiE" { target c++14 } } }
Jason Merrill Dec. 14, 2023, 10:09 p.m. UTC | #3
On 12/14/23 16:08, Patrick Palka wrote:
> On Thu, 14 Dec 2023, Jason Merrill wrote:
> 
>> On 12/14/23 14:17, Patrick Palka wrote:
>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
>>> trunk?  Do we want to condition this on abi_check (19)?
>>
>> I think we do, sadly.
> 
> Sounds good, like so?  Bootstrap and regtest in progress.
> 
> -- >8 --
> 
> Subject: [PATCH] c++: abi_tag attribute on templates [PR109715]
> 
> As with other declaration attributes, we need to look through
> TEMPLATE_DECL when looking up the abi_tag attribute.
> 
> 	PR c++/109715
> 
> gcc/cp/ChangeLog:
> 
> 	* mangle.cc (get_abi_tags): Look through TEMPLATE_DECL.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/abi/abi-tag25.C: New test.
> 	* g++.dg/abi/abi-tag25a.C: New test.
> ---
>   gcc/cp/mangle.cc                      |  6 ++++++
>   gcc/testsuite/g++.dg/abi/abi-tag25.C  | 17 +++++++++++++++++
>   gcc/testsuite/g++.dg/abi/abi-tag25a.C | 11 +++++++++++
>   3 files changed, 34 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
>   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25a.C
> 
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index 0684f0e6038..e3383df1836 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -530,6 +530,12 @@ get_abi_tags (tree t)
>     if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
>       t = TREE_TYPE (t);
>   
> +  if (TREE_CODE (t) == TEMPLATE_DECL
> +      && DECL_TEMPLATE_RESULT (t)
> +      /* We used to ignore abi_tag on function and variable templates.  */
> +      && abi_check (19))
> +    t = DECL_TEMPLATE_RESULT (t);

Generally I try to call abi_check only when we know that there's 
something that will change the mangling, so here only if the template 
has ABI tags.  I suppose the only downside is a second mangling that 
produces the same name and gets ignored in mangle_decl so we don't need 
to be too strict about it, but it shouldn't be too hard to do that here?

Jason
Patrick Palka Dec. 15, 2023, 12:59 a.m. UTC | #4
On Thu, 14 Dec 2023, Jason Merrill wrote:

> On 12/14/23 16:08, Patrick Palka wrote:
> > On Thu, 14 Dec 2023, Jason Merrill wrote:
> > 
> > > On 12/14/23 14:17, Patrick Palka wrote:
> > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > > > trunk?  Do we want to condition this on abi_check (19)?
> > > 
> > > I think we do, sadly.
> > 
> > Sounds good, like so?  Bootstrap and regtest in progress.
> > 
> > -- >8 --
> > 
> > Subject: [PATCH] c++: abi_tag attribute on templates [PR109715]
> > 
> > As with other declaration attributes, we need to look through
> > TEMPLATE_DECL when looking up the abi_tag attribute.
> > 
> > 	PR c++/109715
> > 
> > gcc/cp/ChangeLog:
> > 
> > 	* mangle.cc (get_abi_tags): Look through TEMPLATE_DECL.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > 	* g++.dg/abi/abi-tag25.C: New test.
> > 	* g++.dg/abi/abi-tag25a.C: New test.
> > ---
> >   gcc/cp/mangle.cc                      |  6 ++++++
> >   gcc/testsuite/g++.dg/abi/abi-tag25.C  | 17 +++++++++++++++++
> >   gcc/testsuite/g++.dg/abi/abi-tag25a.C | 11 +++++++++++
> >   3 files changed, 34 insertions(+)
> >   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
> >   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25a.C
> > 
> > diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> > index 0684f0e6038..e3383df1836 100644
> > --- a/gcc/cp/mangle.cc
> > +++ b/gcc/cp/mangle.cc
> > @@ -530,6 +530,12 @@ get_abi_tags (tree t)
> >     if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
> >       t = TREE_TYPE (t);
> >   +  if (TREE_CODE (t) == TEMPLATE_DECL
> > +      && DECL_TEMPLATE_RESULT (t)
> > +      /* We used to ignore abi_tag on function and variable templates.  */
> > +      && abi_check (19))
> > +    t = DECL_TEMPLATE_RESULT (t);
> 
> Generally I try to call abi_check only when we know that there's something
> that will change the mangling, so here only if the template has ABI tags.  I
> suppose the only downside is a second mangling that produces the same name and
> gets ignored in mangle_decl so we don't need to be too strict about it, but it
> shouldn't be too hard to do that here?

D'oh, good point..  Otherwise IIUC we'd wastefully mangle most function
and variable templates (and perhaps their instantiations) twice when ABI
checks are enabled.

So like the following then?  Implemented using a recurse call but
we could easily implement it without recursion if anything.

-- >8 --

We need to look through TEMPLATE_DECL when looking up the abi_tag
attribute (as with other function and variable declaration attributes).

	PR c++/109715

gcc/cp/ChangeLog:

	* mangle.cc (get_abi_tags): Strip TEMPLATE_DECL before looking
	up the abi_tag attribute.

gcc/testsuite/ChangeLog:

	* g++.dg/abi/abi-tag25.C: New test.
	* g++.dg/abi/abi-tag25a.C: New test.
---
 gcc/cp/mangle.cc                      | 10 ++++++++++
 gcc/testsuite/g++.dg/abi/abi-tag25.C  | 17 +++++++++++++++++
 gcc/testsuite/g++.dg/abi/abi-tag25a.C | 11 +++++++++++
 3 files changed, 38 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
 create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25a.C

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 0684f0e6038..365d470f46e 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -530,6 +530,16 @@ get_abi_tags (tree t)
   if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
     t = TREE_TYPE (t);
 
+  if (TREE_CODE (t) == TEMPLATE_DECL && DECL_TEMPLATE_RESULT (t))
+    {
+      tree tags = get_abi_tags (DECL_TEMPLATE_RESULT (t));
+      /* We used to overlook abi_tag on function and variable templates.  */
+      if (tags && abi_check (19))
+	return tags;
+      else
+	return NULL_TREE;
+    }
+
   tree attrs;
   if (TYPE_P (t))
     attrs = TYPE_ATTRIBUTES (t);
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25.C b/gcc/testsuite/g++.dg/abi/abi-tag25.C
new file mode 100644
index 00000000000..9847f0dccc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag25.C
@@ -0,0 +1,17 @@
+// PR c++/109715
+// { dg-do compile { target c++11 } }
+
+template<class T>
+[[gnu::abi_tag("foo")]] void fun() { }
+
+template void fun<int>();
+
+#if __cpp_variable_templates
+template<class T>
+[[gnu::abi_tag("foo")]] int var = 0;
+
+template int var<int>;
+#endif
+
+// { dg-final { scan-assembler "_Z3funB3fooIiEvv" } }
+// { dg-final { scan-assembler "_Z3varB3fooIiE" { target c++14 } } }
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25a.C b/gcc/testsuite/g++.dg/abi/abi-tag25a.C
new file mode 100644
index 00000000000..9499b5614cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag25a.C
@@ -0,0 +1,11 @@
+// PR c++/109715
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fabi-version=18 -fabi-compat-version=18 -Wabi=0" }
+
+#include "abi-tag25.C"
+
+// { dg-warning "mangled name" "" { target *-*-* } 5 }
+// { dg-warning "mangled name" "" { target *-*-* } 11 }
+
+// { dg-final { scan-assembler "_Z3funIiEvv" } }
+// { dg-final { scan-assembler "_Z3varIiE" { target c++14 } } }
Jason Merrill Dec. 15, 2023, 1:26 a.m. UTC | #5
On 12/14/23 19:59, Patrick Palka wrote:
> On Thu, 14 Dec 2023, Jason Merrill wrote:
> 
>> On 12/14/23 16:08, Patrick Palka wrote:
>>> On Thu, 14 Dec 2023, Jason Merrill wrote:
>>>
>>>> On 12/14/23 14:17, Patrick Palka wrote:
>>>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
>>>>> trunk?  Do we want to condition this on abi_check (19)?
>>>>
>>>> I think we do, sadly.
>>>
>>> Sounds good, like so?  Bootstrap and regtest in progress.
>>>
>>> -- >8 --
>>>
>>> Subject: [PATCH] c++: abi_tag attribute on templates [PR109715]
>>>
>>> As with other declaration attributes, we need to look through
>>> TEMPLATE_DECL when looking up the abi_tag attribute.
>>>
>>> 	PR c++/109715
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> 	* mangle.cc (get_abi_tags): Look through TEMPLATE_DECL.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 	* g++.dg/abi/abi-tag25.C: New test.
>>> 	* g++.dg/abi/abi-tag25a.C: New test.
>>> ---
>>>    gcc/cp/mangle.cc                      |  6 ++++++
>>>    gcc/testsuite/g++.dg/abi/abi-tag25.C  | 17 +++++++++++++++++
>>>    gcc/testsuite/g++.dg/abi/abi-tag25a.C | 11 +++++++++++
>>>    3 files changed, 34 insertions(+)
>>>    create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
>>>    create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25a.C
>>>
>>> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
>>> index 0684f0e6038..e3383df1836 100644
>>> --- a/gcc/cp/mangle.cc
>>> +++ b/gcc/cp/mangle.cc
>>> @@ -530,6 +530,12 @@ get_abi_tags (tree t)
>>>      if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
>>>        t = TREE_TYPE (t);
>>>    +  if (TREE_CODE (t) == TEMPLATE_DECL
>>> +      && DECL_TEMPLATE_RESULT (t)
>>> +      /* We used to ignore abi_tag on function and variable templates.  */
>>> +      && abi_check (19))
>>> +    t = DECL_TEMPLATE_RESULT (t);
>>
>> Generally I try to call abi_check only when we know that there's something
>> that will change the mangling, so here only if the template has ABI tags.  I
>> suppose the only downside is a second mangling that produces the same name and
>> gets ignored in mangle_decl so we don't need to be too strict about it, but it
>> shouldn't be too hard to do that here?
> 
> D'oh, good point..  Otherwise IIUC we'd wastefully mangle most function
> and variable templates (and perhaps their instantiations) twice when ABI
> checks are enabled.
> 
> So like the following then?  Implemented using a recurse call but
> we could easily implement it without recursion if anything.

OK, thanks.

> -- >8 --
> 
> We need to look through TEMPLATE_DECL when looking up the abi_tag
> attribute (as with other function and variable declaration attributes).
> 
> 	PR c++/109715
> 
> gcc/cp/ChangeLog:
> 
> 	* mangle.cc (get_abi_tags): Strip TEMPLATE_DECL before looking
> 	up the abi_tag attribute.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/abi/abi-tag25.C: New test.
> 	* g++.dg/abi/abi-tag25a.C: New test.
> ---
>   gcc/cp/mangle.cc                      | 10 ++++++++++
>   gcc/testsuite/g++.dg/abi/abi-tag25.C  | 17 +++++++++++++++++
>   gcc/testsuite/g++.dg/abi/abi-tag25a.C | 11 +++++++++++
>   3 files changed, 38 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25.C
>   create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag25a.C
> 
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index 0684f0e6038..365d470f46e 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -530,6 +530,16 @@ get_abi_tags (tree t)
>     if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
>       t = TREE_TYPE (t);
>   
> +  if (TREE_CODE (t) == TEMPLATE_DECL && DECL_TEMPLATE_RESULT (t))
> +    {
> +      tree tags = get_abi_tags (DECL_TEMPLATE_RESULT (t));
> +      /* We used to overlook abi_tag on function and variable templates.  */
> +      if (tags && abi_check (19))
> +	return tags;
> +      else
> +	return NULL_TREE;
> +    }
> +
>     tree attrs;
>     if (TYPE_P (t))
>       attrs = TYPE_ATTRIBUTES (t);
> diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25.C b/gcc/testsuite/g++.dg/abi/abi-tag25.C
> new file mode 100644
> index 00000000000..9847f0dccc8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/abi-tag25.C
> @@ -0,0 +1,17 @@
> +// PR c++/109715
> +// { dg-do compile { target c++11 } }
> +
> +template<class T>
> +[[gnu::abi_tag("foo")]] void fun() { }
> +
> +template void fun<int>();
> +
> +#if __cpp_variable_templates
> +template<class T>
> +[[gnu::abi_tag("foo")]] int var = 0;
> +
> +template int var<int>;
> +#endif
> +
> +// { dg-final { scan-assembler "_Z3funB3fooIiEvv" } }
> +// { dg-final { scan-assembler "_Z3varB3fooIiE" { target c++14 } } }
> diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25a.C b/gcc/testsuite/g++.dg/abi/abi-tag25a.C
> new file mode 100644
> index 00000000000..9499b5614cd
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/abi-tag25a.C
> @@ -0,0 +1,11 @@
> +// PR c++/109715
> +// { dg-do compile { target c++11 } }
> +// { dg-additional-options "-fabi-version=18 -fabi-compat-version=18 -Wabi=0" }
> +
> +#include "abi-tag25.C"
> +
> +// { dg-warning "mangled name" "" { target *-*-* } 5 }
> +// { dg-warning "mangled name" "" { target *-*-* } 11 }
> +
> +// { dg-final { scan-assembler "_Z3funIiEvv" } }
> +// { dg-final { scan-assembler "_Z3varIiE" { target c++14 } } }
diff mbox series

Patch

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 0684f0e6038..1fbd879c116 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -527,6 +527,9 @@  get_abi_tags (tree t)
   if (!t || TREE_CODE (t) == NAMESPACE_DECL)
     return NULL_TREE;
 
+  if (TREE_CODE (t) == TEMPLATE_DECL && DECL_TEMPLATE_RESULT (t))
+    t = DECL_TEMPLATE_RESULT (t);
+
   if (DECL_P (t) && DECL_DECLARES_TYPE_P (t))
     t = TREE_TYPE (t);
 
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag25.C b/gcc/testsuite/g++.dg/abi/abi-tag25.C
new file mode 100644
index 00000000000..9847f0dccc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/abi-tag25.C
@@ -0,0 +1,17 @@ 
+// PR c++/109715
+// { dg-do compile { target c++11 } }
+
+template<class T>
+[[gnu::abi_tag("foo")]] void fun() { }
+
+template void fun<int>();
+
+#if __cpp_variable_templates
+template<class T>
+[[gnu::abi_tag("foo")]] int var = 0;
+
+template int var<int>;
+#endif
+
+// { dg-final { scan-assembler "_Z3funB3fooIiEvv" } }
+// { dg-final { scan-assembler "_Z3varB3fooIiE" { target c++14 } } }