public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation
@ 2023-05-26 20:25 nikolasklauser at berlin dot de
  2023-05-26 20:31 ` [Bug c++/110000] " ldionne.2 at gmail dot com
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: nikolasklauser at berlin dot de @ 2023-05-26 20:25 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

            Bug ID: 110000
           Summary: GCC should implement
                    exclude_from_explicit_instantiation
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nikolasklauser at berlin dot de
  Target Milestone: ---

`exclude_from_explicit_instantiation` is an attribute implemented by clang. It
tells the compiler that a function should not be part of an explicit
instantiation. This allows libraries to have greater control over which
functions are part of their ABI and which aren't. It is used extensively in
libc++ to keep the ABI surface as small as possible. Currently, libc++ uses
always_inline if exclude_from_explicit_instantiation isn't available, resulting
in almost every function in the library being declared as always_inline.
Replacing always_inline with exclude_from_explicit_instantiation would
approximately halve the time it takes to run the libc++ test suite with GCC.
(removing always_inline brings the time down to about the same as clang takes)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
@ 2023-05-26 20:31 ` ldionne.2 at gmail dot com
  2023-05-26 20:33 ` pinskia at gcc dot gnu.org
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ldionne.2 at gmail dot com @ 2023-05-26 20:31 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

Louis Dionne <ldionne.2 at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ldionne.2 at gmail dot com

--- Comment #1 from Louis Dionne <ldionne.2 at gmail dot com> ---
I implemented the attribute in Clang and it was pretty easy for me even as a
novice compiler person, so I expect it wouldn't be too hard to implement in GCC
either.

Removing always_inline does not only lead to better compile times, but also to
better code generation and obviously a better debugging experience. We
investigated various other alternatives that wouldn't require using the
attribute but we concluded that we really had to if we wanted to keep a tight
grip on our ABI surface while still allowing users to explicitly instantiate
stdlib classes (which they are allowed to as long as they provide at least one
user-defined type).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
  2023-05-26 20:31 ` [Bug c++/110000] " ldionne.2 at gmail dot com
@ 2023-05-26 20:33 ` pinskia at gcc dot gnu.org
  2023-05-26 20:35 ` pinskia at gcc dot gnu.org
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-26 20:33 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I am trying to understand the exact details here?
https://releases.llvm.org/9.0.0/tools/clang/docs/AttributeReference.html#exclude-from-explicit-instantiation

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
  2023-05-26 20:31 ` [Bug c++/110000] " ldionne.2 at gmail dot com
  2023-05-26 20:33 ` pinskia at gcc dot gnu.org
@ 2023-05-26 20:35 ` pinskia at gcc dot gnu.org
  2023-05-26 20:42 ` nikolasklauser at berlin dot de
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-26 20:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I am getting a feeling this attribute is well defined enough.

Is it really just supposed to block explicit instantiation of templates?
Is there a decent set of testcases that can be used to match up the
implementations here? Because I suspect without those it will be implemented
slightly different.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (2 preceding siblings ...)
  2023-05-26 20:35 ` pinskia at gcc dot gnu.org
@ 2023-05-26 20:42 ` nikolasklauser at berlin dot de
  2023-05-27 10:39 ` fw at gcc dot gnu.org
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: nikolasklauser at berlin dot de @ 2023-05-26 20:42 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #4 from Nikolas Klauser <nikolasklauser at berlin dot de> ---
(In reply to Andrew Pinski from comment #3)
> I am getting a feeling this attribute is well defined enough.
> 
> Is it really just supposed to block explicit instantiation of templates?
> Is there a decent set of testcases that can be used to match up the
> implementations here? Because I suspect without those it will be implemented
> slightly different.

The attribute was originally implemented in https://reviews.llvm.org/D51789.
There are also a few test cases, but I don't know if they are enough. If there
are any cases which aren't clear I'm happy to work them out (and maybe update
the implementation in clang if necessary).
Yes, it is only to block explicit instantiation of member functions (and to
tell the compiler that they have to be instantiated implicitly, obviously).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (3 preceding siblings ...)
  2023-05-26 20:42 ` nikolasklauser at berlin dot de
@ 2023-05-27 10:39 ` fw at gcc dot gnu.org
  2023-05-27 23:40 ` nikolasklauser at berlin dot de
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fw at gcc dot gnu.org @ 2023-05-27 10:39 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

Florian Weimer <fw at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fw at gcc dot gnu.org

--- Comment #5 from Florian Weimer <fw at gcc dot gnu.org> ---
How hard is this to use in practice? With current Clang, this:

“
template <class T>
class S {
  __attribute__ ((visibility ("hidden"), exclude_from_explicit_instantiation))
  int f1 ();
  int f2 ();
};

template <class T> int
S<T>::f1 ()
{
  return 1;
}

template <class T> int
S<T>::f2 ()
{
  return f1 ();
}

template class S<int>;
”

still inlines S<int>::f1 into S<int>::f2. This may not threaten future
evolution of the implementation in this particular case, but it would certainly
be helpful to have some guides similar to
<https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B>.
Clang's attribute documentation describes what happens, but it doesn't comment
on the actual implications for ABI compatibility.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (4 preceding siblings ...)
  2023-05-27 10:39 ` fw at gcc dot gnu.org
@ 2023-05-27 23:40 ` nikolasklauser at berlin dot de
  2023-05-28  6:13 ` fw at gcc dot gnu.org
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: nikolasklauser at berlin dot de @ 2023-05-27 23:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #6 from Nikolas Klauser <nikolasklauser at berlin dot de> ---
(In reply to Florian Weimer from comment #5)
> How hard is this to use in practice? With current Clang, this:
> 
> “
> template <class T>
> class S {
>   __attribute__ ((visibility ("hidden"),
> exclude_from_explicit_instantiation))
>   int f1 ();
>   int f2 ();
> };
> 
> template <class T> int
> S<T>::f1 ()
> {
>   return 1;
> }
> 
> template <class T> int
> S<T>::f2 ()
> {
>   return f1 ();
> }
> 
> template class S<int>;
> ”
> 
> still inlines S<int>::f1 into S<int>::f2. This may not threaten future
> evolution of the implementation in this particular case, but it would
> certainly be helpful to have some guides similar to
> <https://community.kde.org/Policies/
> Binary_Compatibility_Issues_With_C%2B%2B>. Clang's attribute documentation
> describes what happens, but it doesn't comment on the actual implications
> for ABI compatibility.

It doesn't have any inherent implications on ABI compatibility. Without other
tricks you still have to stay ABI compatible between versions of your function.
Some of the options are
- always inlining (this doesn't require the new attribute, but has numerous
drawbacks)
- making the functions have internal linkage (this would require the new
attribute, but note that clang's `internal_linkage` attribute seems to do this
implicitly)
- changing the mangling of the function whenever you change the ABI (this is
what libc++ currently does, through `abi_tag`s which change with every release)
I'm sure there are other ways to achieve this. These are the ways libc++
achieved this throughout it's history (that I know of). There might be better
ways, but the only problem with the current approach I am aware of is that the
ABI tag adds a few extra bytes per symbol. Compared to always inlining or
having one instance of a function per translation unit, that solution seems
pretty good to me. 

Essentially, to be able to do anything with a function you want, you have to
add `__attribute__((visibility("hidden"), exclude_from_explicit_instantiation,
abi_tag("some-versioning-scheme")))`, where 
- `visibility("hidden")` is to avoid exporting the symbol from any libraries
- `exclude_from_explicit_instantiation` is to avoid problems when users try to
explicitly instantiate a class template (or you want to provide an explicit
instantiation, but only some functions should be part of the ABI) and
- `abi_tag` is to avoid problems when users compile their code with different
versions of the library (essentially duplicating functions which may not be ABI
compatible)

Does that make sense?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (5 preceding siblings ...)
  2023-05-27 23:40 ` nikolasklauser at berlin dot de
@ 2023-05-28  6:13 ` fw at gcc dot gnu.org
  2023-05-28 14:31 ` nikolasklauser at berlin dot de
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fw at gcc dot gnu.org @ 2023-05-28  6:13 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #7 from Florian Weimer <fw at gcc dot gnu.org> ---
(In reply to Nikolas Klauser from comment #6)
> Does that make sense?

Not quite. I was trying to suggest that you also need to suppress all
inter-procedural analysis. This will inhibit quite a few useful optimizations.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (6 preceding siblings ...)
  2023-05-28  6:13 ` fw at gcc dot gnu.org
@ 2023-05-28 14:31 ` nikolasklauser at berlin dot de
  2023-05-31 15:40 ` ldionne.2 at gmail dot com
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: nikolasklauser at berlin dot de @ 2023-05-28 14:31 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #8 from Nikolas Klauser <nikolasklauser at berlin dot de> ---
(In reply to Florian Weimer from comment #7)
> (In reply to Nikolas Klauser from comment #6)
> > Does that make sense?
> 
> Not quite. I was trying to suggest that you also need to suppress all
> inter-procedural analysis. This will inhibit quite a few useful
> optimizations.

Why would you need to do that? As long as any functions that are part of the
ABI don't change in a non-benign way, everything is fine. If an
implementation-detail function doesn't get inlined, but the public function
does, it's fine because the detail function gets emitted by every TU that uses
it, which means that it'll always be there as long as some function relies on
the symbol. If the implementation-detail function gets inlined, the code will
obviously be there - no need to have a symbol anywhere.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (7 preceding siblings ...)
  2023-05-28 14:31 ` nikolasklauser at berlin dot de
@ 2023-05-31 15:40 ` ldionne.2 at gmail dot com
  2023-05-31 16:48 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ldionne.2 at gmail dot com @ 2023-05-31 15:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #9 from Louis Dionne <ldionne.2 at gmail dot com> ---
(In reply to Andrew Pinski from comment #3)
> I am getting a feeling this attribute is well defined enough.
> 
> Is it really just supposed to block explicit instantiation of templates?
> Is there a decent set of testcases that can be used to match up the
> implementations here? Because I suspect without those it will be implemented
> slightly different.

Is there anything specific you're thinking about that would be insufficiently
defined? It's possible that that's the case, and if so then we can define it
properly and make sure Clang/GCC are aligned on the semantics.

This is quite a painful issue for libc++ on GCC since the current solution is
to use `always_inline`, which has too many downsides. It used to be just an
annoyance, but with the addition of libraries like `std::format`, using
`always_inline` leads to a library that is literally unusable in some cases
(compile times and code size just skyrockets). So yeah, we're much willing to
collaborate in order to make this work.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (8 preceding siblings ...)
  2023-05-31 15:40 ` ldionne.2 at gmail dot com
@ 2023-05-31 16:48 ` redi at gcc dot gnu.org
  2023-05-31 16:52 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: redi at gcc dot gnu.org @ 2023-05-31 16:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement

--- Comment #10 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Using always_inline on everything is simply wrong: GCC will refuse to inline
some functions and the user gets an error that they cannot avoid. There's no
command-line option or pragma that can be used to compile the code anyway, it's
just un-compilable.

I don't really understand the aim here. You're trying to avoid the user's
program ever containing a symbol generated from any libc++ code? So that they
can't ever have a dependency on those symbols, and the definitions can change?

Honestly, the cure seems worse than the disease.

Just because code is inlined, it doesn't mean it's immune from ABI
incompatibilities (it avoids some kinds of problems, but doesn't help with
others).

And if all libc++ functions have an abi_tag courtesy of the HIDE_FROM_ABI
macro, why does it matter whether explicit instantiations include them anyway?

Your include/__config says:

The symbol is given an ABI tag that changes with each version of libc++. This
ensures
that no ODR violation can arise from mixing two TUs compiled with different
versions
of libc++ where we would have changed the definition of a symbol. If the
symbols shared
the same name, the ODR would require that their definitions be token-by-token
equivalent,
which basically prevents us from being able to make any change to any function
in our
headers.

Again, the cure seems worse than the disease.

Your compiler and/or linker and/or dynamic loader can define what happens here,
so the ODR violation doesn't lead to nasal demons. If your definitions are not
token-by-token identical then what happens in practice is that you get two
definitions emitted in different TUs and the linker picks one. There's no
actual UB here. Applying this to every single function in the library just in
case you want to change it some day seems like major overkill.

But on the topic of this enhancement request, I don't see why functions should
be excluded from explicit instantiation if they're already abi-tagged. Do you
want to be able to change these functions in ABI-incompatible ways between
major revisions of the library?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (9 preceding siblings ...)
  2023-05-31 16:48 ` redi at gcc dot gnu.org
@ 2023-05-31 16:52 ` redi at gcc dot gnu.org
  2023-05-31 17:33 ` nikolasklauser at berlin dot de
  2023-06-01 18:00 ` ldionne.2 at gmail dot com
  12 siblings, 0 replies; 14+ messages in thread
From: redi at gcc dot gnu.org @ 2023-05-31 16:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #10)
> Do you want to be able to change these functions in
> ABI-incompatible ways between major revisions of the library?

Sorry, that was unclear, I meant to ask if you want to change them in
ABI-incompatible ways without bumping the version in the abi_tag?

e.g. change std::__1::vector<int, std::__1::allocator<int>
>::__clear[abi:v15007]() in an ABI-incompatible way, without changing the tag
to [abi:v15008]?

Because if the tag is going to change anyway, what does it matter if the user
has instantiations of the old [abi:v15007] symbol in their lib?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (10 preceding siblings ...)
  2023-05-31 16:52 ` redi at gcc dot gnu.org
@ 2023-05-31 17:33 ` nikolasklauser at berlin dot de
  2023-06-01 18:00 ` ldionne.2 at gmail dot com
  12 siblings, 0 replies; 14+ messages in thread
From: nikolasklauser at berlin dot de @ 2023-05-31 17:33 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #12 from Nikolas Klauser <nikolasklauser at berlin dot de> ---
(In reply to Jonathan Wakely from comment #10)
> Using always_inline on everything is simply wrong: GCC will refuse to inline
> some functions and the user gets an error that they cannot avoid. There's no
> command-line option or pragma that can be used to compile the code anyway,
> it's just un-compilable.
Yes, that is one of the many problems with `always_inline` which we want to
avoid.
> I don't really understand the aim here. You're trying to avoid the user's
> program ever containing a symbol generated from any libc++ code? So that
> they can't ever have a dependency on those symbols, and the definitions can
> change?
Depends on what you mean by "never have a dependency on those symbols". It's
fine to emit the symbol and link against it, as long as every TU that relies on
it will also have a weak definition.
> Honestly, the cure seems worse than the disease.
> 
> Just because code is inlined, it doesn't mean it's immune from ABI
> incompatibilities (it avoids some kinds of problems, but doesn't help with
> others).
Could you elaborate on the other problems?
> And if all libc++ functions have an abi_tag courtesy of the HIDE_FROM_ABI
> macro, why does it matter whether explicit instantiations include them
> anyway?
It becomes a problem when people try to have an explicit instantiation in a
shared library, since all the symbols also have visibility("hidden"). The
result are linker errors.
> Your include/__config says:
> 
> The symbol is given an ABI tag that changes with each version of libc++.
> This ensures
> that no ODR violation can arise from mixing two TUs compiled with different
> versions
> of libc++ where we would have changed the definition of a symbol. If the
> symbols shared
> the same name, the ODR would require that their definitions be
> token-by-token equivalent,
> which basically prevents us from being able to make any change to any
> function in our
> headers.
> 
> Again, the cure seems worse than the disease.
> 
> Your compiler and/or linker and/or dynamic loader can define what happens
> here, so the ODR violation doesn't lead to nasal demons. If your definitions
> are not token-by-token identical then what happens in practice is that you
> get two definitions emitted in different TUs and the linker picks one.
> There's no actual UB here. Applying this to every single function in the
> library just in case you want to change it some day seems like major
> overkill.
> 
> But on the topic of this enhancement request, I don't see why functions
> should be excluded from explicit instantiation if they're already
> abi-tagged. Do you want to be able to change these functions in
> ABI-incompatible ways between major revisions of the library?

(In reply to Jonathan Wakely from comment #11)
> (In reply to Jonathan Wakely from comment #10)
> > Do you want to be able to change these functions in
> > ABI-incompatible ways between major revisions of the library?
> 
> Sorry, that was unclear, I meant to ask if you want to change them in
> ABI-incompatible ways without bumping the version in the abi_tag?
No. Being able to change the implementation in ABI-incompatible ways between
versions is the whole point of the tag.
> e.g. change std::__1::vector<int, std::__1::allocator<int>
> >::__clear[abi:v15007]() in an ABI-incompatible way, without changing the
> tag to [abi:v15008]?
> 
> Because if the tag is going to change anyway, what does it matter if the
> user has instantiations of the old [abi:v15007] symbol in their lib?
That's completely fine (and in fact the goal of adding
`exclude_from_explicit_instantiation`). The idea is that the library contains
the symbols it uses, and we can remove functions, change the ABI of functions,
or whatever else. Everything that a TU relies upon will be part of that TU.
When linking, the symbols will be deduplicated, and most people will have just
one version of a given function in their binary. If you ever have multiple
versions for whatever reason, it's fine because the ABI tags +
exclude_from_explicit_instantiation make sure the symbol exists somewhere and
has it's own name.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation
  2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
                   ` (11 preceding siblings ...)
  2023-05-31 17:33 ` nikolasklauser at berlin dot de
@ 2023-06-01 18:00 ` ldionne.2 at gmail dot com
  12 siblings, 0 replies; 14+ messages in thread
From: ldionne.2 at gmail dot com @ 2023-06-01 18:00 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110000

--- Comment #13 from Louis Dionne <ldionne.2 at gmail dot com> ---
Nikolas already answered some, but just to expand on this:

> But on the topic of this enhancement request, I don't see why functions should be excluded from explicit instantiation if they're already abi-tagged. Do you want to be able to change these functions in ABI-incompatible ways between major revisions of the library?

What we're trying to avoid here is that if a user has an explicit instantiation
*declaration*, we don't want their code to start depending on the fact that
some-implementation-detail-member-function exists in the class. So for example,
if we have:

  template <class T>
  class vector {
  public:
    iterator begin() { ... }
    iterator end() { ... }

    void __push_back_helper(T const&) { ... }
  };

If the user has something like this in their code:

  extern template class vector<Foo>;

The compiler will then assume that the following methods are defined elsewhere
(presumably where the explicit instantiation actually happens):

    iterator vector<Foo>::begin();
    iterator vector<Foo>::end();
    void vector<Foo>::__push_back_helper(Foo const&);

Whether those methods are ABI-tagged or not doesn't matter, the compiler will
still emit code that contains external references to those methods. That's fine
if we're OK with committing to these methods in the long term, but if we want
to keep the flexibility of removing or changing these methods in arbitrary
ways, what we really want here is for the compiler not to assume that the
explicit instantiation includes these methods, and instead emit its own
linkonce_odr copy in the TU (which then gets deduplicated across TUs in case
the same function was defined elsewher too).

Does this make sense?

Regarding ABI tags, like Nikolas explained, the idea is that in most cases,
users actually have a single version of libc++ in their whole program, so all
the symbols from libc++ have the same ABI tag, and the linker will deduplicate
everything. In case a users happens to mix versions of libc++ in different TUs,
then the right thing will happen: functions with different ABI tags won't be
deduplicated as-if they were token-for-token equivalent and only the functions
that don't have an ABI tag will be deduplicated cause they're the same across
all TUs (but we do commit to stability for those symbols).

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-06-01 18:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-26 20:25 [Bug c++/110000] New: GCC should implement exclude_from_explicit_instantiation nikolasklauser at berlin dot de
2023-05-26 20:31 ` [Bug c++/110000] " ldionne.2 at gmail dot com
2023-05-26 20:33 ` pinskia at gcc dot gnu.org
2023-05-26 20:35 ` pinskia at gcc dot gnu.org
2023-05-26 20:42 ` nikolasklauser at berlin dot de
2023-05-27 10:39 ` fw at gcc dot gnu.org
2023-05-27 23:40 ` nikolasklauser at berlin dot de
2023-05-28  6:13 ` fw at gcc dot gnu.org
2023-05-28 14:31 ` nikolasklauser at berlin dot de
2023-05-31 15:40 ` ldionne.2 at gmail dot com
2023-05-31 16:48 ` redi at gcc dot gnu.org
2023-05-31 16:52 ` redi at gcc dot gnu.org
2023-05-31 17:33 ` nikolasklauser at berlin dot de
2023-06-01 18:00 ` ldionne.2 at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).