Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 73 additions & 56 deletions src/core/stdc/config.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* D header file for C99.
/***
* D compatible types that correspond to various basic types in associated
* C and C++ compilers.
*
* Copyright: Copyright Sean Kelly 2005 - 2009.
* License: Distributed under the
Expand All @@ -12,6 +13,53 @@

module core.stdc.config;

version (StdDdoc)
{
/***
* Used for a signed integer type that corresponds in size to the associated
* C compiler's `long` type.
*/
alias c_long = int;

/***
* Used for an unsigned integer type that corresponds in size to the associated
* C compiler's `unsigned long` type.
*/
alias c_ulong = uint;

/***
* Used for a signed integer type that corresponds in size and mangling to the associated
* C++ compiler's `long` type.
*/
alias cpp_long = c_long;

/***
* Used for an unsigned integer type that corresponds in size and mangling to the associated
* C++ compiler's `unsigned long` type.
*/
alias cpp_ulong = c_ulong;

/***
* Used for a floating point type that corresponds in size and mangling to the associated
* C++ compiler's `long double` type.
*/
alias c_long_double = real;

/***
* Used for an unsigned integer type that corresponds in size and mangling to the associated
* C++ compiler's `size_t` type.
*/
alias cpp_size_t = size_t;

/***
* Used for a signed integer type that corresponds in size and mangling to the associated
* C++ compiler's `ptrdiff_t` type.
*/
alias cpp_ptrdiff_t = ptrdiff_t;
}
else
{

version (OSX)
version = Darwin;
else version (iOS)
Expand All @@ -21,40 +69,10 @@ else version (TVOS)
else version (WatchOS)
version = Darwin;

extern (C):
@trusted: // Types only.
nothrow:
@nogc:

version( Windows )
{
struct __c_long
{
pure nothrow @nogc @safe:
this(int x) { lng = x; }
int lng;
alias lng this;
}

struct __c_ulong
{
pure nothrow @nogc @safe:
this(uint x) { lng = x; }
uint lng;
alias lng this;
}

/*
* This is cpp_long instead of c_long because:
* 1. Implicit casting of an int to __c_long doesn't happen, because D doesn't
* allow constructor calls in implicit conversions.
* 2. long lng;
* cast(__c_long)lng;
* does not work because lng has to be implicitly cast to an int in the constructor,
* and since that truncates it is not done.
* Both of these break existing code, so until we find a resolution the types are named
* cpp_xxxx.
*/
enum __c_long : int;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had no clue that it was even legal to declare an enum with no members. That seems very weird. Is the point of doing this instead of using an alias so that it's a distinct type from int? I guess that that would mean that this technique is a typedef of sorts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the point of doing this instead of using an alias so that it's a distinct type from int?

Yes, so that the compiler can do special mangling for that type. Although I don't see how it's any better than a struct. I proposed to add support for adding pragma(mangle) to alias declarations but Walter doesn't seem to like that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you go down that path, you'll discover you've reinvented enums.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmdavis BTW, one use case of declaring an enum without any members is to use it as a UDA that doesn't contain any data.

enum __c_ulong : uint;

alias __c_long cpp_long;
alias __c_ulong cpp_ulong;
Expand All @@ -66,26 +84,19 @@ else version( Posix )
{
static if( (void*).sizeof > int.sizeof )
{
enum __c_long : long;
enum __c_ulong : ulong;

alias __c_long cpp_long;
alias __c_ulong cpp_ulong;

alias long c_long;
alias ulong c_ulong;
}
else
{
struct __c_long
{
pure nothrow @nogc @safe:
this(int x) { lng = x; }
int lng;
alias lng this;
}

struct __c_ulong
{
pure nothrow @nogc @safe:
this(uint x) { lng = x; }
uint lng;
alias lng this;
}
enum __c_long : int;
enum __c_ulong : uint;

alias __c_long cpp_long;
alias __c_ulong cpp_ulong;
Expand All @@ -103,13 +114,7 @@ version( CRuntime_Microsoft )
* to generate the correct name mangling and correct function call/return
* ABI conformance.
*/
struct __c_long_double
{
pure nothrow @nogc @safe:
this(double d) { ld = d; }
double ld;
alias ld this;
}
enum __c_long_double : double;

alias __c_long_double c_long_double;
}
Expand Down Expand Up @@ -150,3 +155,15 @@ else version( SDC )
}

static assert(is(c_long_double), "c_long_double needs to be declared for this platform/architecture.");

version (Darwin)
{
alias cpp_size_t = cpp_ulong;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we do the other way around, i.e. alias size_t = cpp_ulong in object.d? This would be to avoid having to use cpp_size_t instead of size_t.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan to do that separately.

alias cpp_ptrdiff_t = cpp_long;
}
else
{
alias cpp_size_t = size_t;
alias cpp_ptrdiff_t = ptrdiff_t;
}
}