C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Specify the mangled name

From: Thiago Macieira <thiago_at_[hidden]>
Date: Tue, 04 Feb 2025 14:53:43 -0800
On Tuesday 4 February 2025 12:59:16 Pacific Standard Time Tiago Freire wrote:
> The ability to forward declare nested classes is one of my motivations.
>
> I wouldn’t go into the direction of requiring compilers to automatically
> just “find me the right header files” and not specify how that works. If I
> may take the discussion around “#pragma once”, I would say that lose rules
> regarding how the magic happens is a recipe for disaster.

That's a good point.

> From my understanding you can actually do quite a lot without much magic.
>
> I have found 2 categories of problems.
> 1. Non-aliased types. Where the forwarded type is the actual name of the
> type. It will be one of class, struct, or union, without needing to specify
> it as a class, struct, or union.
>
> 1 is super easy, it looks like pretty much everything works, template,
> constexpr, function calls, etc... I haven't noticed a problem yet.
> Everything that you can do with a trivially forward declared type you would
> be able to do with this. The only difference is you don’t have to specify
> class, struct, or union, it’s one of those 3.

Yeah, no, that's not going to work. The compiler must know what it is. Unions
are not structs/classes, so the mangling is allowed to be different, and it is
for MSVC. MSVC also mangles structs differently from classes, in violation of
the C++ standard, but we shouldn't design a feature that is DOA for MSVC.

GCC & Clang also support an ABI-tagging of types (__attribute__((abi))) which
will influence the mangling, so those need to be provided too. This would allow
MSVC to also include another of its standards-violating requirements: the
representation format for PMFs formed from this class (see
https://learn.microsoft.com/en-us/cpp/cpp/inheritance-keywords?view=msvc-170).
And it would allow other attributes that the implementation might decide
should be queryable without the full definition (like __declspec(uuid) for
__uuidof).

Therefore, the solution for resolving needs to be a mechanism that inform the
compiler of all of that.

> 2. Aliased types. A type "defined" by using typedef or using.
>
> 2 is much more complicated, because the actual name will be different from
> the know name. (ex. std::string)

Well, not really. The definition for std::string can simply be:

typename std::basic_string;
namespace std {
    using string = basic_string<char>;
}

This moves the goalpost, of course. But if we have a means of finding
std::basic_string, which we need for point (1), then (2) becomes easy.
 
> I think you can make function calls sort of work.
> As long as function prototypes are defined with the same name as the alias
> name, it is trivial to resolve. For that you would need extra data in
> object files to keep track of aliases so that it can resolve the actual
> names when linking. I think that information would also need to be
> transitive and passed around static libraries such that you can handle
> linking between multiple libraries, it’s more to track but looks doable.

I think that's overengineering and dramatically reduces the chance of
adoption. If we require binary format and toolchain updates, the barrier of
adoption goes up. It will have ripple effects many years later, as we learn all
of the effects (intentional or not) of having them.

As an example, inline variables not marked namespace-scope static. There were
bugfixes to dynamic loaders many years after their introduction in C++11 -
modules with active inline variables cannot be unloaded from memory. Another
example are thread_local variables and their de-initialisation order. This
last one was a major headache for me in the last 6 months, because I made a
well-intentioned change from pthread_setspecific to them, but found out that
the many OSes have very buggy implementations and wildly different behaviours.
There are several of them that violate the C++ standard because the C
libraries backing them are provided by a vendor different from the C++
compiler, and those didn't (and still don't!) know that they had to make
changes.

GCC and Clang developers reading this: please don't automatically opt-in to
behaviour you discover to be broken. Instead, make it so you have to
explicitly select it (q.v. __cxa_thread_atexit).
 
> For constexpr functions, you can make it work if the name used is the same
> (or a qualified version thereof), if it isn’t, then link time it would be
> to late to do anything.

Right: the compiler must have somehow found the full definition by the time
this compilation finished.
 
-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Principal Engineer - Intel DCAI Platform & System Engineering

Received on 2025-02-04 22:53:49