[committed] d: Merge upstream dmd, druntime 5f7552bb28, phobos 67a47cf39.

Message ID 20230317045256.34563-1-ibuclaw@gdcproject.org
State Committed
Commit 328477f6ee82d27fa6bb09617644d409be300688
Headers
Series [committed] d: Merge upstream dmd, druntime 5f7552bb28, phobos 67a47cf39. |

Commit Message

Iain Buclaw March 17, 2023, 4:52 a.m. UTC
  Hi,

This patch merges the D front-end and run-time library with upstream dmd
5f7552bb28, and standard library with phobos 67a47cf39.

Synchronizing the latest bug fixes in the upcoming v2.103.0 release.

D front-end changes:

	- Import dmd v2.103.0-rc.1.

D runtime changes:

	- Import druntime v2.103.0-rc.1.

Phobos changes:

	- Import phobos v2.103.0-rc.1.

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 5f7552bb28.
	* dmd/VERSION: Bump version to v2.103.0-rc.1.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32,
committed to mainline.

Regards,
Iain.

---
libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime 5f7552bb28.
	* src/MERGE: Merge upstream phobos 67a47cf39.
---
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/VERSION                             |   2 +-
 gcc/d/dmd/dinterpret.d                        |  12 ++-
 gcc/d/dmd/dsymbol.d                           |  21 +++-
 gcc/d/dmd/expressionsem.d                     | 102 +++++++++++++++++-
 gcc/d/dmd/typesem.d                           |   1 +
 gcc/d/dmd/typinf.d                            |   5 +-
 gcc/testsuite/gdc.test/compilable/test16213.d |   8 ++
 gcc/testsuite/gdc.test/compilable/test17351.d |   9 ++
 gcc/testsuite/gdc.test/compilable/test19295.d |  10 ++
 .../gdc.test/compilable/testcorrectthis.d     |  37 +++++++
 .../gdc.test/fail_compilation/fail23760.d     |  27 +++++
 .../gdc.test/fail_compilation/fail61.d        |   2 +-
 .../gdc.test/fail_compilation/fail_circular.d |  15 +--
 .../gdc.test/fail_compilation/ice19295.d      |  18 ----
 .../gdc.test/fail_compilation/ice23781.d      |  10 ++
 .../gdc.test/fail_compilation/ice9439.d       |   4 +-
 libphobos/libdruntime/MERGE                   |   2 +-
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/std/math/exponential.d          |  30 ++++--
 libphobos/src/std/traits.d                    |  27 ++++-
 21 files changed, 295 insertions(+), 51 deletions(-)
 create mode 100644 gcc/testsuite/gdc.test/compilable/test16213.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/test19295.d
 create mode 100644 gcc/testsuite/gdc.test/compilable/testcorrectthis.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail23760.d
 delete mode 100644 gcc/testsuite/gdc.test/fail_compilation/ice19295.d
 create mode 100644 gcc/testsuite/gdc.test/fail_compilation/ice23781.d
  

Patch

diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 269eebfc483..986925e8bdc 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-4ca4140e584c055a8a9bc727e56a97ebcecd61e0
+5f7552bb2829b75d5e36cc767a476e1ab35147b7
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 8b24f92dab7..da496a2ceeb 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@ 
-v2.103.0-beta.1
+v2.103.0-rc.1
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 9073b0db2f8..e6ef704be86 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -2036,7 +2036,7 @@  public:
         }
         auto er = interpret(e.e1, istate, CTFEGoal.LValue);
         if (auto ve = er.isVarExp())
-            if (ve.var == istate.fd.vthis)
+            if (istate && ve.var == istate.fd.vthis)
                 er = interpret(er, istate);
 
         if (exceptionOrCant(er))
@@ -2117,6 +2117,16 @@  public:
                     return CTFEExp.cantexp;
                 assert(e.type);
 
+                // There's a terrible hack in `dmd.dsymbolsem` that special case
+                // a struct with all zeros to an `ExpInitializer(BlitExp(IntegerExp(0)))`
+                // There's matching code for it in e2ir (toElem's visitAssignExp),
+                // so we need the same hack here.
+                // This does not trigger for global as they get a normal initializer.
+                if (auto ts = e.type.isTypeStruct())
+                    if (auto ae = e.isBlitExp())
+                        if (ae.e2.op == EXP.int64)
+                            e = ts.defaultInitLiteral(loc);
+
                 if (e.op == EXP.construct || e.op == EXP.blit)
                 {
                     AssignExp ae = cast(AssignExp)e;
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index aa478f2fea2..e7ce93ee067 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -2162,10 +2162,23 @@  extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
                  * or a variable (in which case an expression is created in
                  * toir.c).
                  */
-                auto e = new VoidInitializer(Loc.initial);
-                e.type = Type.tsize_t;
-                v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
-                v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
+
+                // https://issues.dlang.org/show_bug.cgi?id=16213
+                // For static arrays $ is known at compile time,
+                // so declare it as a manifest constant.
+                auto tsa = ce.type ? ce.type.isTypeSArray() : null;
+                if (tsa)
+                {
+                    auto e = new ExpInitializer(loc, tsa.dim);
+                    v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
+                }
+                else
+                {
+                    auto e = new VoidInitializer(Loc.initial);
+                    e.type = Type.tsize_t;
+                    v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
+                    v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
+                }
             }
             *pvar = v;
         }
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index d186abc0552..632ea11cdc0 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1155,6 +1155,69 @@  L1:
     return e1;
 }
 
+/*
+ * Check whether `outerFunc` and `calledFunc` have the same `this`.
+ * If `calledFunc` is the member of a base class of the class that contains
+ * `outerFunc` we consider that they have the same this.
+ *
+ * This function is used to test whether `this` needs to be prepended to
+ * a function call or function symbol. For example:
+ *
+ * struct X
+ * {
+ *    void gun() {}
+ * }
+ * struct A
+ * {
+ *      void fun() {}
+ *      void sun()
+ *      {
+ *          fun();
+ *          X.gun();  // error
+ *      }
+ * }
+ *
+ * When `fun` is called, `outerfunc` = `sun` and `calledFunc = `fun`.
+ * `sun` is a member of `A` and `fun` is also a member of `A`, therefore
+ * `this` can be prepended to `fun`. When `gun` is called (it will result
+ * in an error, but that is not relevant here), which is a member of `X`,
+ * no `this` is needed because the outer function does not have the same
+ * `this` as `gun`.
+ *
+ * Returns:
+ *  `true` if outerFunc and calledFunc may use the same `this` pointer.
+ * `false` otherwise.
+ */
+private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc)
+{
+    auto thisAd = outerFunc.isMemberLocal();
+    if (!thisAd)
+        return false;
+
+    auto requiredAd = calledFunc.isMemberLocal();
+    if (!requiredAd)
+        return false;
+
+    if (thisAd == requiredAd)
+        return true;
+
+    // outerfunc is the member of a base class that contains calledFunc,
+    // then we consider that they have the same this.
+    auto cd = requiredAd.isClassDeclaration();
+    if (!cd)
+        return false;
+
+    if (cd.isBaseOf2(thisAd.isClassDeclaration()))
+        return true;
+
+    // if outerfunc is the member of a nested aggregate, then let
+    // getRightThis take care of this.
+    if (thisAd.isNested())
+        return true;
+
+    return false;
+}
+
 /***************************************
  * Pull out any properties.
  */
@@ -5209,7 +5272,8 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 if (exp.f.checkNestedReference(sc, exp.loc))
                     return setError();
 
-                if (hasThis(sc))
+                auto memberFunc = hasThis(sc);
+                if (memberFunc && haveSameThis(memberFunc, exp.f))
                 {
                     // Supply an implicit 'this', as in
                     //    this.ident
@@ -6892,8 +6956,6 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
         AggregateDeclaration ad = f.isMemberLocal();
         if (f.needThis())
             e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
-        if (e.e1.op == EXP.error)
-            return setError();
 
         if (f.type.ty == Tfunction)
         {
@@ -7207,7 +7269,8 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
                 }
                 if (f.needThis())
                 {
-                    if (hasThis(sc))
+                    auto memberFunc = hasThis(sc);
+                    if (memberFunc && haveSameThis(memberFunc, f))
                     {
                         /* Should probably supply 'this' after overload resolution,
                          * not before.
@@ -7309,6 +7372,14 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
             goto case Terror;
         }
 
+        if (sc.flags & SCOPE.Cfile && exp.type && exp.type.toBasetype().ty == Tvoid)
+        {
+            // https://issues.dlang.org/show_bug.cgi?id=23752
+            // `&*((void*)(0))` is allowed in C
+            result = exp;
+            return;
+        }
+
         if (exp.checkValue())
             return setError();
 
@@ -12311,6 +12382,29 @@  private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         Type t1 = exp.e1.type;
         Type t2 = exp.e2.type;
+
+        // https://issues.dlang.org/show_bug.cgi?id=23767
+        // `cast(void*) 0` should be treated as `null` so the ternary expression
+        // gets the pointer type of the other branch
+        if (sc.flags & SCOPE.Cfile)
+        {
+            static void rewriteCNull(ref Expression e, ref Type t)
+            {
+                if (!t.isTypePointer())
+                    return;
+                if (auto ie = e.optimize(WANTvalue).isIntegerExp())
+                {
+                    if (ie.getInteger() == 0)
+                    {
+                        e = new NullExp(e.loc, Type.tnull);
+                        t = Type.tnull;
+                    }
+                }
+            }
+            rewriteCNull(exp.e1, t1);
+            rewriteCNull(exp.e2, t2);
+        }
+
         if (t1.ty == Tnoreturn)
         {
             exp.type = t2;
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 84561ac467a..c668199e5f7 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -4176,6 +4176,7 @@  Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
             }
             if (v.type.ty == Terror)
             {
+                e.error("type of variable `%s` has errors", v.toPrettyChars);
                 return ErrorExp.get();
             }
 
diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d
index 2ca71437d14..38a39b46108 100644
--- a/gcc/d/dmd/typinf.d
+++ b/gcc/d/dmd/typinf.d
@@ -34,8 +34,9 @@  import core.stdc.stdio;
  *      loc   = the location for reporting line numbers in errors
  *      torig = the type to generate the `TypeInfo` object for
  *      sc    = the scope
+ *      genObjCode = if true, object code will be generated for the obtained TypeInfo
  */
-extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
+extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc, bool genObjCode = true)
 {
     // printf("genTypeInfo() %s\n", torig.toChars());
 
@@ -80,7 +81,7 @@  extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope
 
         // generate a COMDAT for other TypeInfos not available as builtins in
         // druntime
-        if (!isUnqualifiedClassInfo && !builtinTypeInfo(t))
+        if (!isUnqualifiedClassInfo && !builtinTypeInfo(t) && genObjCode)
         {
             if (sc) // if in semantic() pass
             {
diff --git a/gcc/testsuite/gdc.test/compilable/test16213.d b/gcc/testsuite/gdc.test/compilable/test16213.d
new file mode 100644
index 00000000000..ccf77c6c948
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test16213.d
@@ -0,0 +1,8 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=16213
+
+enum Id(size_t i) = i;
+void main()
+{
+    int[5] y;
+    y[ Id!($) - 1 ] = 3;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test17351.d b/gcc/testsuite/gdc.test/compilable/test17351.d
index fffe92c4d58..a04ade12476 100644
--- a/gcc/testsuite/gdc.test/compilable/test17351.d
+++ b/gcc/testsuite/gdc.test/compilable/test17351.d
@@ -1,3 +1,4 @@ 
+// PERMUTE_ARGS: -preview=in
 bool fun(S)(ref S[3] a) { assert(a == [42, 84, 169]); return true; }
 bool fun2(S)(ref S a) { return true; }
 void main()
@@ -14,4 +15,12 @@  void test2()
 {
     static immutable int[2] P = [ 0, 1 ];
     static assert(f2(P) == 1);
+    immutable BigInt a, b;
+    static assert(glob1.twice == b.twice);
+    static assert(a.twice == b.twice);
 }
+
+struct BigInt { int[64] big; }
+BigInt twice (in BigInt v) @safe pure nothrow @nogc { return v; }
+
+immutable BigInt glob1 = BigInt.init;
diff --git a/gcc/testsuite/gdc.test/compilable/test19295.d b/gcc/testsuite/gdc.test/compilable/test19295.d
new file mode 100644
index 00000000000..a32a317c08e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19295.d
@@ -0,0 +1,10 @@ 
+struct S1(T...) {
+    auto fun() {
+        static assert(__traits(compiles, &T[0]));
+    }
+}
+
+struct S2 {
+    void gun() {}
+    S1!gun overloaded;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testcorrectthis.d b/gcc/testsuite/gdc.test/compilable/testcorrectthis.d
new file mode 100644
index 00000000000..3adc0628236
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/testcorrectthis.d
@@ -0,0 +1,37 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=10886
+
+struct A
+{
+    @property int foo() { return 0; }
+    int bar() { return 0; }
+}
+
+struct B
+{
+    void bar()
+    {
+        alias f = typeof(A.foo);  // NG
+        alias b = typeof(A.bar);  // ok
+    }
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=21288
+
+struct XA
+{
+    int p;
+}
+
+struct XB
+{
+    XA a() { return XA.init; }
+    alias a this;
+}
+
+struct XC
+{
+    void foo()
+    {
+        static assert(XB.p.stringof == "p"); // Error: this for s needs to be type B not type C
+    }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23760.d b/gcc/testsuite/gdc.test/fail_compilation/fail23760.d
new file mode 100644
index 00000000000..fbca6ecd797
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail23760.d
@@ -0,0 +1,27 @@ 
+// https://issues.dlang.org/show_bug.cgi?id=23760
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail23760.d(16): Error: type of variable `fail23760.A.state` has errors
+fail_compilation/fail23760.d(16): Error: `(A).state` cannot be resolved
+fail_compilation/fail23760.d(21): Error: template instance `fail23760.JavaBridge!(A)` error instantiating
+fail_compilation/fail23760.d(24):        instantiated from here: `JavaClass!(A)`
+---
+*/
+
+class JavaBridge(Class)
+{
+    static if(is(typeof(__traits(getMember, Class, "state")))) {}
+    alias T = __traits(getOverloads, Class, "state");
+}
+
+class JavaClass(CRTP)
+{
+    JavaBridge!(CRTP) _javaDBridge;
+}
+
+class A : JavaClass!A
+{
+    State* state;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail61.d b/gcc/testsuite/gdc.test/fail_compilation/fail61.d
index 90c3b39977d..1386bd664a3 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail61.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail61.d
@@ -4,7 +4,7 @@  TEST_OUTPUT:
 fail_compilation/fail61.d(22): Error: no property `B` for type `fail61.A.B`
 fail_compilation/fail61.d(23): Error: no property `B` for type `fail61.A.B`
 fail_compilation/fail61.d(32): Error: no property `A2` for type `fail61.B2`
-fail_compilation/fail61.d(41): Error: `this` for `foo` needs to be type `B3` not type `fail61.C3`
+fail_compilation/fail61.d(41): Error: need `this` for `foo` of type `void()`
 ---
 */
 
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_circular.d b/gcc/testsuite/gdc.test/fail_compilation/fail_circular.d
index 186444e459a..e67fabce91d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_circular.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_circular.d
@@ -110,12 +110,15 @@  struct S6
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/fail_circular.d(123): Error: circular reference to variable `fail_circular.C.a1`
-fail_compilation/fail_circular.d(125): Error: circular reference to variable `fail_circular.C.b1`
-fail_compilation/fail_circular.d(127): Error: circular reference to variable `fail_circular.C.c1`
-fail_compilation/fail_circular.d(130): Error: circular reference to variable `fail_circular.C.a1a`
-fail_compilation/fail_circular.d(133): Error: circular reference to variable `fail_circular.C.b1a`
-fail_compilation/fail_circular.d(136): Error: circular reference to variable `fail_circular.C.c1a`
+fail_compilation/fail_circular.d(126): Error: circular reference to variable `fail_circular.C.a1`
+fail_compilation/fail_circular.d(128): Error: circular reference to variable `fail_circular.C.b1`
+fail_compilation/fail_circular.d(130): Error: circular reference to variable `fail_circular.C.c1`
+fail_compilation/fail_circular.d(133): Error: circular reference to variable `fail_circular.C.a1a`
+fail_compilation/fail_circular.d(132): Error: type of variable `fail_circular.C.a1b` has errors
+fail_compilation/fail_circular.d(136): Error: circular reference to variable `fail_circular.C.b1a`
+fail_compilation/fail_circular.d(135): Error: type of variable `fail_circular.C.b1b` has errors
+fail_compilation/fail_circular.d(139): Error: circular reference to variable `fail_circular.C.c1a`
+fail_compilation/fail_circular.d(138): Error: type of variable `fail_circular.C.c1b` has errors
 ---
 */
 class C
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice19295.d b/gcc/testsuite/gdc.test/fail_compilation/ice19295.d
deleted file mode 100644
index a92f5f8384c..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/ice19295.d
+++ /dev/null
@@ -1,18 +0,0 @@ 
-/*
-TEST_OUTPUT:
----
-fail_compilation/ice19295.d(11): Error: `this` for `gun` needs to be type `S2` not type `S1!(gun)`
-fail_compilation/ice19295.d(11):        while evaluating `pragma(msg, &gun)`
-fail_compilation/ice19295.d(17): Error: template instance `ice19295.S1!(gun)` error instantiating
----
-*/
-struct S1(T...) {
-    auto fun() {
-        pragma(msg, &T[0]);
-    }
-}
-
-struct S2 {
-    void gun() {}
-    S1!gun overloaded;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice23781.d b/gcc/testsuite/gdc.test/fail_compilation/ice23781.d
new file mode 100644
index 00000000000..7adc11607db
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice23781.d
@@ -0,0 +1,10 @@ 
+/**
+TEST_OUTPUT:
+---
+fail_compilation/ice23781.d(10): Error: variable `b` cannot be read at compile time
+---
+**/
+struct Bar { int i; }
+ref const(Bar) func1 (const return ref Bar b) { return b; }
+immutable E1 = Bar();
+enum E2 = &E1.func1();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9439.d b/gcc/testsuite/gdc.test/fail_compilation/ice9439.d
index a9e70083802..5b2a8b12031 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice9439.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice9439.d
@@ -1,8 +1,8 @@ 
 /*
 TEST_OUTPUT:
 ---
-fail_compilation/ice9439.d(12): Error: `this` for `foo` needs to be type `Derived` not type `ice9439.Base`
-fail_compilation/ice9439.d(12):        while evaluating: `static assert((__error).foo())`
+fail_compilation/ice9439.d(12): Error: need `this` for `foo` of type `int()`
+fail_compilation/ice9439.d(12):        while evaluating: `static assert(foo())`
 fail_compilation/ice9439.d(19): Error: template instance `ice9439.Base.boo!(foo)` error instantiating
 ---
 */
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 269eebfc483..986925e8bdc 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-4ca4140e584c055a8a9bc727e56a97ebcecd61e0
+5f7552bb2829b75d5e36cc767a476e1ab35147b7
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index a2191397599..e72db81b710 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-454dff14dcbd005f9550302c5836ef8e06ab663a
+67a47cf39d52b3cb3ae4117c0237415e03737f8a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d
index fd1ff244b62..8290479248d 100644
--- a/libphobos/src/std/math/exponential.d
+++ b/libphobos/src/std/math/exponential.d
@@ -3033,13 +3033,13 @@  private
                 4.5270000862445199635215E-5,
             ];
             static immutable double[7] logp1Q = [
-                1.0000000000000000000000E0,
                 6.0118660497603843919306E1,
                 2.1642788614495947685003E2,
                 3.0909872225312059774938E2,
                 2.2176239823732856465394E2,
                 8.3047565967967209469434E1,
                 1.5062909083469192043167E1,
+                1.0000000000000000000000E0,
             ];
 
             static immutable double[7] log10P = [
@@ -3101,13 +3101,13 @@  private
                  4.5270000862E-5,
             ];
             static immutable float[7] logp1Q = [
-                1.00000000000E0,
                 6.01186604976E1,
                 2.16427886144E2,
                 3.09098722253E2,
                 2.21762398237E2,
                 8.30475659679E1,
                 1.50629090834E1,
+                1.00000000000E0,
             ];
 
             // log2 and log10 uses the same coefficients as log.
@@ -3323,7 +3323,7 @@  private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc
     }
     static foreach (F; AliasSeq!(float, double, real))
     {{
-        F[2][24] vals = [
+        scope F[2][] vals = [
             [F(1), F(0x0p+0)], [F(2), F(0x1.62e42fefa39ef358p-1)],
             [F(4), F(0x1.62e42fefa39ef358p+0)], [F(8), F(0x1.0a2b23f3bab73682p+1)],
             [F(16), F(0x1.62e42fefa39ef358p+1)], [F(32), F(0x1.bb9d3beb8c86b02ep+1)],
@@ -3335,6 +3335,9 @@  private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc
             [F(17), F(0x1.6aa6bc1fa7f79cfp+1)], [F(31), F(0x1.b78ce48912b59f12p+1)],
             [F(33), F(0x1.bf8d8f4d5b8d1038p+1)], [F(63), F(0x1.09291e8e3181b20ep+2)],
             [F(65), F(0x1.0b292939429755ap+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(0.1), F(-0x1.26bb1bbb5551582ep+1)], [F(0.25), F(-0x1.62e42fefa39ef358p+0)],
+            [F(0.75), F(-0x1.269621134db92784p-2)], [F(0.875), F(-0x1.1178e8227e47bde4p-3)],
+            [F(10), F(0x1.26bb1bbb5551582ep+1)], [F(100), F(0x1.26bb1bbb5551582ep+2)],
             [F(10000), F(0x1.26bb1bbb5551582ep+3)],
         ];
         testLog(vals);
@@ -3572,7 +3575,7 @@  Ldone:
     }
     static foreach (F; AliasSeq!(float, double, real))
     {{
-        F[2][24] vals = [
+        scope F[2][] vals = [
             [F(1), F(0x0p+0)], [F(2), F(0x1.34413509f79fef32p-2)],
             [F(4), F(0x1.34413509f79fef32p-1)], [F(8), F(0x1.ce61cf8ef36fe6cap-1)],
             [F(16), F(0x1.34413509f79fef32p+0)], [F(32), F(0x1.8151824c7587eafep+0)],
@@ -3584,7 +3587,9 @@  Ldone:
             [F(17), F(0x1.3afeb354b7d9731ap+0)], [F(31), F(0x1.7dc9e145867e62eap+0)],
             [F(33), F(0x1.84bd545e4baeddp+0)], [F(63), F(0x1.cca1950e4511e192p+0)],
             [F(65), F(0x1.d01b16f9433cf7b8p+0)], [F(-0), -F.infinity], [F(0), -F.infinity],
-            [F(10000), F(0x1p+2)],
+            [F(0.1), F(-0x1p+0)], [F(0.25), F(-0x1.34413509f79fef32p-1)],
+            [F(0.75), F(-0x1.ffbfc2bbc7803758p-4)], [F(0.875), F(-0x1.db11ed766abf432ep-5)],
+            [F(10), F(0x1p+0)], [F(100), F(0x1p+1)], [F(10000), F(0x1p+2)],
         ];
         testLog10(vals);
     }}
@@ -3758,7 +3763,7 @@  private T log1pImpl(T)(T x) @safe pure nothrow @nogc
     }
     static foreach (F; AliasSeq!(float, double, real))
     {{
-        F[2][24] vals = [
+        scope F[2][] vals = [
             [F(1), F(0x1.62e42fefa39ef358p-1)], [F(2), F(0x1.193ea7aad030a976p+0)],
             [F(4), F(0x1.9c041f7ed8d336bp+0)], [F(8), F(0x1.193ea7aad030a976p+1)],
             [F(16), F(0x1.6aa6bc1fa7f79cfp+1)], [F(32), F(0x1.bf8d8f4d5b8d1038p+1)],
@@ -3770,6 +3775,9 @@  private T log1pImpl(T)(T x) @safe pure nothrow @nogc
             [F(17), F(0x1.71f7b3a6b918664cp+1)], [F(31), F(0x1.bb9d3beb8c86b02ep+1)],
             [F(33), F(0x1.c35fc81b90df59c6p+1)], [F(63), F(0x1.0a2b23f3bab73682p+2)],
             [F(65), F(0x1.0c234da4a23a6686p+2)], [F(-0), F(-0x0p+0)], [F(0), F(0x0p+0)],
+            [F(0.1), F(0x1.8663f793c46c69cp-4)], [F(0.25), F(0x1.c8ff7c79a9a21ac4p-3)],
+            [F(0.75), F(0x1.1e85f5e7040d03ep-1)], [F(0.875), F(0x1.41d8fe84672ae646p-1)],
+            [F(10), F(0x1.32ee3b77f374bb7cp+1)], [F(100), F(0x1.275e2271bba30be4p+2)],
             [F(10000), F(0x1.26bbed6fbd84182ep+3)],
         ];
         testLog1p(vals);
@@ -3981,7 +3989,7 @@  Ldone:
     }
     static foreach (F; AliasSeq!(float, double, real))
     {{
-        F[2][24] vals = [
+        scope F[2][] vals = [
             [F(1), F(0x0p+0)], [F(2), F(0x1p+0)],
             [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)],
             [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)],
@@ -3993,6 +4001,9 @@  Ldone:
             [F(17), F(0x1.0598fdbeb244c5ap+2)], [F(31), F(0x1.3d118d66c4d4e554p+2)],
             [F(33), F(0x1.42d75a6eb1dfb0e6p+2)], [F(63), F(0x1.7e8bc1179e0caa9cp+2)],
             [F(65), F(0x1.816e79685c2d2298p+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(0.1), F(-0x1.a934f0979a3715fcp+1)], [F(0.25), F(-0x1p+1)],
+            [F(0.75), F(-0x1.a8ff971810a5e182p-2)], [F(0.875), F(-0x1.8a8980abfbd32668p-3)],
+            [F(10), F(0x1.a934f0979a3715fcp+1)], [F(100), F(0x1.a934f0979a3715fcp+2)],
             [F(10000), F(0x1.a934f0979a3715fcp+3)],
         ];
         testLog2(vals);
@@ -4178,7 +4189,7 @@  private T logbImpl(T)(T x) @trusted pure nothrow @nogc
     }
     static foreach (F; AliasSeq!(float, double, real))
     {{
-        F[2][24] vals = [
+        scope F[2][] vals = [
             [F(1), F(0x0p+0)], [F(2), F(0x1p+0)],
             [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)],
             [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)],
@@ -4190,6 +4201,9 @@  private T logbImpl(T)(T x) @trusted pure nothrow @nogc
             [F(17), F(0x1p+2)], [F(31), F(0x1p+2)],
             [F(33), F(0x1.4p+2)], [F(63), F(0x1.4p+2)],
             [F(65), F(0x1.8p+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(0.1), F(-0x1p+2)], [F(0.25), F(-0x1p+1)],
+            [F(0.75), F(-0x1p+0)], [F(0.875), F(-0x1p+0)],
+            [F(10), F(0x1.8p+1)], [F(100), F(0x1.8p+2)],
             [F(10000), F(0x1.ap+3)],
         ];
         testLogb(vals);
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index bbbca69b22b..f4d011bbad9 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -8812,6 +8812,30 @@  template getSymbolsByUDA(alias symbol, alias attribute)
     static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23776
+@safe pure nothrow @nogc unittest
+{
+    struct T
+    {
+        struct Tag {}
+        @Tag struct MyStructA {}
+        @Tag struct MyStructB {}
+        @Tag struct MyStructC {}
+    }
+    alias tcomponents = getSymbolsByUDA!(T, T.Tag);
+    static assert(tcomponents.length > 0);
+
+    struct X
+    {
+        struct Tag {}
+        @Tag enum MyEnumA;
+        @Tag enum MyEnumB;
+        @Tag enum MyEnumC;
+    }
+    alias xcomponents = getSymbolsByUDA!(X, X.Tag);
+    static assert(xcomponents.length > 0);
+}
+
 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
 // https://issues.dlang.org/show_bug.cgi?id=18624
 @safe unittest
@@ -8866,7 +8890,8 @@  private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
             alias member = __traits(getMember, symbol, names[0]);
 
             // Filtering not compiled members such as alias of basic types.
-            static if (isAliasSeq!member || isType!member)
+            static if (isAliasSeq!member ||
+                       (isType!member && !isAggregateType!member && !is(member == enum)))
             {
                 alias getSymbolsByUDAImpl = tail;
             }