From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id EC4143858C30; Wed, 31 May 2023 17:33:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EC4143858C30 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1685554419; bh=xqc9Pe/eDK57C/9uJUzGc/S5LnQHVshOfmt+Qhne0Ao=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Az7mLCOBVCpK22NW3p/mC6Bvo91Ob7few7IAYZeo0ZLBT1wZpLupE1HewUL3snHaX +mX6gvMaF0P1QlZurRpU7CzlITL40vsMgF2IdS6tFzUl6M2s+f65g0o/RKXCMcbweu bGfPJHWWFC2/J8nciZ4tGnWO9//3wHuTZyvv+F1w= From: "nikolasklauser at berlin dot de" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/110000] GCC should implement exclude_from_explicit_instantiation Date: Wed, 31 May 2023 17:33:39 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: unknown X-Bugzilla-Keywords: X-Bugzilla-Severity: enhancement X-Bugzilla-Who: nikolasklauser at berlin dot de X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D110000 --- Comment #12 from Nikolas Klauser --- (In reply to Jonathan Wakely from comment #10) > Using always_inline on everything is simply wrong: GCC will refuse to inl= ine > 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 c= an > 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 relie= s on it will also have a weak definition. > Honestly, the cure seems worse than the disease. >=20 > 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: >=20 > 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 differe= nt > 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. >=20 > Again, the cure seems worse than the disease. >=20 > 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 definiti= ons > 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. >=20 > 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? >=20 > 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 > >::__clear[abi:v15007]() in an ABI-incompatible way, without changing the > tag to [abi:v15008]? >=20 > 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 contai= ns the symbols it uses, and we can remove functions, change the ABI of functio= ns, 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 j= ust 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 a= nd has it's own name.=