d: Merge upstream dmd 1b34fea478, phobos 40ffbb364

D front-end changes:

	- Import latest fixes from dmd v2.111.1-rc.1.

Phobos changes:

	- Import latest fixes from phobos v2.111.1-rc.1.
	- Restore compatibility with older Linux platforms where
	  `getrandom' is unavailable.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 1b34fea478.

libphobos/ChangeLog:

	* src/MERGE: Merge upstream phobos 40ffbb364.
	* Makefile.in: Regenerate.
	* configure: Regenerate.
	* configure.ac: Call DRUNTIME_OS_FEATURES.
	* libdruntime/Makefile.am (AM_DFLAGS): Add OS_DFLAGS.
	* libdruntime/Makefile.in: Regenerate.
	* m4/druntime/os.m4 (DRUNTIME_OS_FEATURES): Define.
	* src/Makefile.am: Add OS_DFLAGS.
	* src/Makefile.in: Regenerate.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/testsuite_flags.in: Add OS_DFLAGS.
This commit is contained in:
Iain Buclaw 2025-04-11 12:39:23 +02:00
parent 882d3b319d
commit b905ce8caf
20 changed files with 210 additions and 43 deletions

View file

@ -1,4 +1,4 @@
51816cd01deee5cc1d7d2c6e1e24788ec655b73e
1b34fea4788136b54ec77c6ed9678754d109fc79
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -421,6 +421,7 @@ struct SourceLoc
uint32_t line;
uint32_t column;
uint32_t fileOffset;
DString fileContent;
};
struct Loc

View file

@ -132,7 +132,7 @@ class Lexer
// debug printf("Lexer::Lexer(%p)\n", base);
// debug printf("lexer.filename = %s\n", filename);
token = Token.init;
this.baseLoc = newBaseLoc(filename, endoffset);
this.baseLoc = newBaseLoc(filename, base[0 .. endoffset]);
this.linnum = 1;
this.base = base;
this.end = base + endoffset;
@ -224,7 +224,7 @@ class Lexer
inTokenStringConstant = 0;
lastDocLine = 0;
baseLoc = newBaseLoc("#defines", slice.length);
baseLoc = newBaseLoc("#defines", slice);
scanloc = baseLoc.getLoc(0);
}

View file

@ -64,7 +64,7 @@ nothrow:
extern (C++) static Loc singleFilename(const char* filename)
{
Loc result;
locFileTable ~= new BaseLoc(filename.toDString, locIndex, 0, [0]);
locFileTable ~= new BaseLoc(filename.toDString, null, locIndex, 0, [0]);
result.index = locIndex++;
return result;
}
@ -235,16 +235,20 @@ struct SourceLoc
uint column; /// column number (starts at 1)
uint fileOffset; /// byte index into file
/// Index `fileOffset` into this to to obtain source code context of this location
const(char)[] fileContent;
// aliases for backwards compatibility
alias linnum = line;
alias charnum = column;
this(const(char)[] filename, uint line, uint column, uint fileOffset = 0) nothrow @nogc pure @safe
this(const(char)[] filename, uint line, uint column, uint fileOffset = 0, const(char)[] fileContent = null) nothrow @nogc pure @safe
{
this.filename = filename;
this.line = line;
this.column = column;
this.fileOffset = fileOffset;
this.fileContent = fileContent;
}
this(Loc loc) nothrow @nogc @trusted
@ -300,15 +304,15 @@ private size_t fileTableIndex(uint index) nothrow @nogc
* Create a new source location map for a file
* Params:
* filename = source file name
* size = space to reserve for locations, equal to the file size in bytes
* fileContent = content of source file
* Returns: new BaseLoc
*/
BaseLoc* newBaseLoc(const(char)* filename, size_t size) nothrow
BaseLoc* newBaseLoc(const(char)* filename, const(char)[] fileContent) nothrow
{
locFileTable ~= new BaseLoc(filename.toDString, locIndex, 1, [0]);
locFileTable ~= new BaseLoc(filename.toDString, fileContent, locIndex, 1, [0]);
// Careful: the endloc of a FuncDeclaration can
// point to 1 past the very last byte in the file, so account for that
locIndex += size + 1;
locIndex += fileContent.length + 1;
return locFileTable[$ - 1];
}
@ -354,6 +358,7 @@ struct BaseLoc
@safe nothrow:
const(char)[] filename; /// Source file name
const(char)[] fileContents; /// Source file contents
uint startIndex; /// Subtract this from Loc.index to get file offset
int startLine = 1; /// Line number at index 0
uint[] lines; /// For each line, the file offset at which it starts. At index 0 there's always a 0 entry.
@ -384,11 +389,11 @@ struct BaseLoc
{
auto fname = filename.toDString;
if (substitutions.length == 0)
substitutions ~= BaseLoc(this.filename, 0, 0);
substitutions ~= BaseLoc(this.filename, null, 0, 0);
if (fname.length == 0)
fname = substitutions[$ - 1].filename;
substitutions ~= BaseLoc(fname, offset, cast(int) (line - lines.length + startLine - 2));
substitutions ~= BaseLoc(fname, null, offset, cast(int) (line - lines.length + startLine - 2));
}
/// Returns: `loc` modified by substitutions from #file / #line directives
@ -408,7 +413,7 @@ struct BaseLoc
private SourceLoc getSourceLoc(uint offset) @nogc
{
const i = getLineIndex(offset);
const sl = SourceLoc(filename, cast(int) (i + startLine), cast(int) (1 + offset - lines[i]), offset);
const sl = SourceLoc(filename, cast(int) (i + startLine), cast(int) (1 + offset - lines[i]), offset, fileContents);
return substitute(sl);
}

View file

@ -3266,9 +3266,19 @@ Type merge(Type type)
case Tsarray:
// prevents generating the mangle if the array dim is not yet known
if (!type.isTypeSArray().dim.isIntegerExp())
return type;
goto default;
if (auto ie = type.isTypeSArray().dim.isIntegerExp())
{
// After TypeSemantic, the length is always converted to size_t, but the parser
// usually generates regular integer types (e.g. in cast(const ubyte[2])) which
// it may try to merge, which then leads to failing implicit conversions as 2LU != 2
// according to Expression.equals. Only merge array types with size_t lengths for now.
// https://github.com/dlang/dmd/issues/21179
if (ie.type != Type.tsize_t)
return type;
goto default;
}
return type;
case Tenum:
break;

View file

@ -0,0 +1,11 @@
// https://github.com/dlang/dmd/issues/21179
void bigEndianToNative(ubyte[2] a) {}
void main()
{
ubyte[] arr;
const ubyte[2] bytes;
bigEndianToNative(bytes);
auto b = cast(const ubyte[2][]) arr;
}

View file

@ -1,22 +1,24 @@
/*
/*
REQUIRED_ARGS: -verrors=context
TEST_OUTPUT:
---
fail_compilation/fail_pretty_errors.d(27): Error: undefined identifier `a`
fail_compilation/fail_pretty_errors.d(29): Error: undefined identifier `a`
a = 1;
^
fail_compilation/fail_pretty_errors.d-mixin-32(32): Error: undefined identifier `b`
fail_compilation/fail_pretty_errors.d(37): Error: cannot implicitly convert expression `5` of type `int` to `string`
fail_compilation/fail_pretty_errors.d-mixin-34(34): Error: undefined identifier `b`
b = 1;
^
fail_compilation/fail_pretty_errors.d(39): Error: cannot implicitly convert expression `5` of type `int` to `string`
string x = 5;
^
fail_compilation/fail_pretty_errors.d(42): Error: mixin `fail_pretty_errors.testMixin2.mixinTemplate!()` error instantiating
fail_compilation/fail_pretty_errors.d(44): Error: mixin `fail_pretty_errors.testMixin2.mixinTemplate!()` error instantiating
mixin mixinTemplate;
^
fail_compilation/fail_pretty_errors.d(48): Error: invalid array operation `"" + ""` (possible missing [])
fail_compilation/fail_pretty_errors.d(50): Error: invalid array operation `"" + ""` (possible missing [])
auto x = ""+"";
^
fail_compilation/fail_pretty_errors.d(48): did you mean to concatenate (`"" ~ ""`) instead ?
fail_compilation/fail_pretty_errors.d(51): Error: cannot implicitly convert expression `1111` of type `int` to `byte`
fail_compilation/fail_pretty_errors.d(50): did you mean to concatenate (`"" ~ ""`) instead ?
fail_compilation/fail_pretty_errors.d(53): Error: cannot implicitly convert expression `1111` of type `int` to `byte`
byte ɑ = 1111;
^
---

View file

@ -258,6 +258,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_DFLAGS = @OS_DFLAGS@
OS_LINK_SPEC = @OS_LINK_SPEC@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@

53
libphobos/configure vendored
View file

@ -655,6 +655,7 @@ DCFG_HAVE_LIBATOMIC
DCFG_HAVE_64BIT_ATOMICS
DCFG_HAVE_ATOMIC_BUILTINS
DCFG_HAVE_QSORT_R
OS_DFLAGS
OS_LINK_SPEC
DCFG_DLPI_TLS_MODID
DRUNTIME_OS_MINFO_BRACKETING_FALSE
@ -11863,7 +11864,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11866 "configure"
#line 11867 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11969,7 +11970,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11972 "configure"
#line 11973 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -14717,6 +14718,54 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
OS_DFLAGS=
case "$druntime_cv_target_os" in
linux*) druntime_target_os_parsed="linux"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getrandom" >&5
$as_echo_n "checking for getrandom... " >&6; }
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/syscall.h>
#include <unistd.h>
int
main ()
{
syscall (__NR_getrandom);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
OS_DFLAGS=-fversion=linux_legacy_emulate_getrandom
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
;;
esac
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'

View file

@ -143,6 +143,7 @@ DRUNTIME_OS_ARM_EABI_UNWINDER
DRUNTIME_OS_MINFO_BRACKETING
DRUNTIME_OS_DLPI_TLS_MODID
DRUNTIME_OS_LINK_SPEC
DRUNTIME_OS_FEATURES
DRUNTIME_LIBRARIES_CLIB
WITH_LOCAL_DRUNTIME([

View file

@ -25,7 +25,8 @@ D_EXTRA_DFLAGS=-fpreview=dip1000 -fpreview=fieldwise -fpreview=dtorfields \
# D flags for compilation
AM_DFLAGS= \
$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS)
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS) \
$(OS_DFLAGS)
# Flags for other kinds of sources
AM_CFLAGS=$(CET_FLAGS)

View file

@ -676,6 +676,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_DFLAGS = @OS_DFLAGS@
OS_LINK_SPEC = @OS_LINK_SPEC@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
@ -783,7 +784,8 @@ D_EXTRA_DFLAGS = -fpreview=dip1000 -fpreview=fieldwise -fpreview=dtorfields \
# D flags for compilation
AM_DFLAGS = \
$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS)
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS) \
$(OS_DFLAGS)
# Flags for other kinds of sources

View file

@ -121,6 +121,33 @@ AC_DEFUN([DRUNTIME_OS_SOURCES],
])
# DRUNTIME_OS_FEATURES
# -----------------------
# Perform various feature checks on the target platform.
AC_DEFUN([DRUNTIME_OS_FEATURES],
[
AC_REQUIRE([DRUNTIME_OS_DETECT])
OS_DFLAGS=
case "$druntime_cv_target_os" in
linux*) druntime_target_os_parsed="linux"
AC_MSG_CHECKING([for getrandom])
AC_LANG_PUSH([C])
AC_TRY_COMPILE([#include <sys/syscall.h>
#include <unistd.h>],[
syscall (__NR_getrandom);
],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
OS_DFLAGS=-fversion=linux_legacy_emulate_getrandom])
AC_LANG_POP([C])
;;
esac
AC_SUBST(OS_DFLAGS)
])
# DRUNTIME_OS_ARM_EABI_UNWINDER
# ------------------------
# Check if using ARM unwinder and substitute DCFG_ARM_EABI_UNWINDER

View file

@ -1,4 +1,4 @@
35977c8029e7bb4dbe1b887688dabebe04ebea02
40ffbb3641495b02815891ee004d4c6e173b1089
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.

View file

@ -26,7 +26,8 @@ D_EXTRA_DFLAGS=-fpreview=dip1000 -fpreview=dtorfields -fpreview=fieldwise \
# D flags for compilation
AM_DFLAGS= \
$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS)
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS) \
$(OS_DFLAGS)
# Flags for other kinds of sources
AM_CFLAGS=$(CET_FLAGS)

View file

@ -411,6 +411,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_DFLAGS = @OS_DFLAGS@
OS_LINK_SPEC = @OS_LINK_SPEC@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
@ -519,7 +520,8 @@ D_EXTRA_DFLAGS = -fpreview=dip1000 -fpreview=dtorfields -fpreview=fieldwise \
# D flags for compilation
AM_DFLAGS = \
$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS)
$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_FLAGS) \
$(OS_DFLAGS)
# Flags for other kinds of sources

View file

@ -534,6 +534,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
// Are we already done with formats? Then just dump each parameter in turn
uint currentArg = 0;
bool lastWasConsumeAll;
while (spec.writeUpToNextSpec(w))
{
if (currentArg == Args.length && !spec.indexStart)
@ -649,7 +651,10 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
}
default:
if (spec.indexEnd == spec.indexEnd.max)
{
lastWasConsumeAll = true;
break;
}
else if (spec.indexEnd == spec.indexStart)
throw new FormatException(
text("Positional specifier %", spec.indexStart, '$', spec.spec,
@ -660,7 +665,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
" index exceeds ", Args.length));
}
}
return currentArg;
return lastWasConsumeAll ? Args.length : currentArg;
}
///
@ -1212,7 +1218,8 @@ if (isSomeString!(typeof(fmt)))
import std.array : appender;
auto w = appender!(char[])();
formattedWrite(w, "%1:$d", 1, 2, 3);
uint count = formattedWrite(w, "%1:$d", 1, 2, 3);
assert(count == 3);
assert(w.data == "123");
}

View file

@ -1774,19 +1774,65 @@ else
version (linux)
{
// `getrandom()` was introduced in Linux 3.17.
version (linux_legacy_emulate_getrandom)
{
/+
Emulates `getrandom()` for backwards compatibility
with outdated kernels and legacy libc versions.
// Shim for missing bindings in druntime
version (none)
import core.sys.linux.sys.random : getrandom;
`getrandom()` was added to the GNU C Library in v2.25.
+/
pragma(msg, "`getrandom()` emulation for legacy Linux targets is enabled.");
/+
On modern kernels (5.6+), `/dev/random` would behave more similar
to `getrandom()`.
However, this emulator was specifically written for systems older
than that. Hence, `/dev/urandom` is the CSPRNG of choice.
<https://web.archive.org/web/20200914181930/https://www.2uo.de/myths-about-urandom/>
+/
private static immutable _pathLinuxSystemCSPRNG = "/dev/urandom";
import core.sys.posix.sys.types : ssize_t;
/+
Linux `getrandom()` emulation built upon `/dev/urandom`.
The fourth parameter (`uint flags`) is happily ignored.
+/
private ssize_t getrandom(
void* buf,
size_t buflen,
uint,
) @system nothrow @nogc
{
import core.stdc.stdio : fclose, fopen, fread;
auto blockDev = fopen(_pathLinuxSystemCSPRNG.ptr, "r");
if (blockDev is null)
assert(false, "System CSPRNG unavailable: `fopen(\"" ~ _pathLinuxSystemCSPRNG ~ "\")` failed.");
scope (exit) fclose(blockDev);
const bytesRead = fread(buf, 1, buflen, blockDev);
return bytesRead;
}
}
else
{
import core.sys.posix.sys.types : ssize_t;
extern extern(C) ssize_t getrandom(
void* buf,
size_t buflen,
uint flags,
) @system nothrow @nogc;
// `getrandom()` was introduced in Linux 3.17.
// Shim for missing bindings in druntime
version (none)
import core.sys.linux.sys.random : getrandom;
else
{
import core.sys.posix.sys.types : ssize_t;
private extern extern(C) ssize_t getrandom(
void* buf,
size_t buflen,
uint flags,
) @system nothrow @nogc;
}
}
}

View file

@ -202,6 +202,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_DFLAGS = @OS_DFLAGS@
OS_LINK_SPEC = @OS_LINK_SPEC@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@

View file

@ -28,7 +28,7 @@ case ${query} in
;;
--gdcflags)
GDCFLAGS_default="-fmessage-length=0 -fno-show-column"
GDCFLAGS_config="@WARN_DFLAGS@ @GDCFLAGS@ @CET_FLAGS@
GDCFLAGS_config="@WARN_DFLAGS@ @GDCFLAGS@ @CET_FLAGS@ @OS_DFLAGS@
@phobos_compiler_shared_flag@
-fall-instantiations -fpreview=dip1000
-fno-release -funittest"