C++ - What is a "type transparent class"?
c++, gcc
Solution
Reading the source code of GCC a bit more, in `semantics.c`:
if (TREE_CODE (t) == RECORD_TYPE
&& !processing_template_decl)
{
tree ns = TYPE_CONTEXT (t);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL
&& DECL_CONTEXT (ns) == std_node
&& DECL_NAME (ns)
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (ns)), "decimal"))
{
const char *n = TYPE_NAME_STRING (t);
if ((strcmp (n, "decimal32") == 0)
|| (strcmp (n, "decimal64") == 0)
|| (strcmp (n, "decimal128") == 0))
TYPE_TRANSPARENT_AGGR (t) = 1;
}
}
This code means that a type is marked transparent if:
- It is a struct, but not a template;
- And it is at namespace level, and that namespace is `std::decimal`.
- And it is named `decimal32`, `decimal64` or `decimal128`.
In `class.c` there is the error check you encountered, and a few more.
And in `mangle.c`:
/* According to the C++ ABI, some library classes are passed the
same as the scalar type of their single member and use the same
mangling. */
if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
type = TREE_TYPE (first_field (type));
The comment is key here. I think it means that a transparent type is replaced for the type of its fist (and only) member, so it can be used anywhere it first member can. For example, in my `include/decimal` the class `std::decimal::decimal32` has a single field of type `__decfloat32` (from a previous `typedef float __decfloat32 __attribute__((mode(SD)));`), so any function that takes a `__decfloat32` can take a `std::decimal::decimal32` and vice-versa. Even the function decoration is done the same. The idea is probably to make this classes ABI compatible with the C types `_Decimal32`, `_Decimal64` and `_Decimal128`.
Now, how are you getting a `class decimal32` with base classes? My only guess is that you are including incompatible (maybe older) header files, with a totally different implementation.
UPDATE
After some investigation, it looks like my guess about the ABI and function decoration is right. The following code:
#include <decimal/decimal>
using namespace std::decimal;
//This is a synonym of C99 _Decimal32, but that is not directly available in C++
typedef float Decimal32 __attribute__((mode(SD)));
void foo(decimal32 a) {}
void foo(Decimal32 a) {}
gives the curious error:
/tmp/ccr61gna.s: Assembler messages:
/tmp/ccr61gna.s:1291: Error: symbol `_Z3fooDf' is already defined
That is, the compiler front-end sees no problem in the overload and emits the asm code, but since both functions are decorated the same the assembler fails.
Now, is this a non-conformance of GCC, as Ben Voigt suggests in the comments? I don't know... you should be able to write overloaded functions with any two different types you want. But OTOH, it is impossible to get the `Decimal32` type without using some compiler extension, so the meaning of this type is implementation defined...
Problem
Using gcc to compile a program that includes support for decimal data types, I recently encountered the following error: `error: type transparent class 'std::decimal::decimal32' has base classes` A quick look at GCC's source tree shows that this error message is found in `gcc/cp/class.c`. What is a "type transparent class"? Why is it an error for such a class to have "base classes"?