]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libphobos/libdruntime/core/demangle.d
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
[thirdparty/gcc.git] / libphobos / libdruntime / core / demangle.d
index 4458b70122be4e566a7df3792b13ee67d27a5da0..ad9b44a1ee5f6ab76566c1895c1df5d264845953 100644 (file)
@@ -54,13 +54,13 @@ pure @safe:
     enum AddType { no, yes }
 
 
-    this( const(char)[] buf_, char[] dst_ = null )
+    this( return const(char)[] buf_, return char[] dst_ = null )
     {
         this( buf_, AddType.yes, dst_ );
     }
 
 
-    this( const(char)[] buf_, AddType addType_, char[] dst_ = null )
+    this( return const(char)[] buf_, AddType addType_, return char[] dst_ = null )
     {
         buf     = buf_;
         addType = addType_;
@@ -208,15 +208,15 @@ pure @safe:
         {
             assert( contains( dst[0 .. len], val ) );
             debug(info) printf( "removing (%.*s)\n", cast(int) val.length, val.ptr );
-
             size_t v = &val[0] - &dst[0];
+            assert( len >= val.length && len <= dst.length );
+            len -= val.length;
             for (size_t p = v; p < len; p++)
                 dst[p] = dst[p + val.length];
-            len -= val.length;
         }
     }
 
-    char[] append( const(char)[] val )
+    char[] append( const(char)[] val ) return scope
     {
         pragma(inline, false); // tame dmd inliner
 
@@ -227,8 +227,7 @@ pure @safe:
             assert( !contains( dst[0 .. len], val ) );
             debug(info) printf( "appending (%.*s)\n", cast(int) val.length, val.ptr );
 
-            if ( &dst[len] == &val[0] &&
-                dst.length - len >= val.length )
+            if ( dst.length - len >= val.length && &dst[len] == &val[0] )
             {
                 // data is already in place
                 auto t = dst[len .. len + val.length];
@@ -254,13 +253,13 @@ pure @safe:
             put(", ");
     }
 
-    char[] put(char c)
+    char[] put(char c) return scope
     {
         char[1] val = c;
         return put(val[]);
     }
 
-    char[] put( const(char)[] val )
+    char[] put( scope const(char)[] val ) return scope
     {
         pragma(inline, false); // tame dmd inliner
 
@@ -278,9 +277,9 @@ pure @safe:
     {
         import core.internal.string;
 
-        UnsignedStringBuf buf;
+        UnsignedStringBuf buf = void;
 
-        auto s = unsignedToTempString(val, buf, 16);
+        auto s = unsignedToTempString!16(val, buf);
         int slen = cast(int)s.length;
         if (slen < width)
         {
@@ -301,7 +300,7 @@ pure @safe:
     }
 
 
-    void silent( lazy void dg )
+    void silent( void delegate() pure @safe dg )
     {
         debug(trace) printf( "silent+\n" );
         debug(trace) scope(success) printf( "silent-\n" );
@@ -431,7 +430,7 @@ pure @safe:
         Digit
         Digit Number
     */
-    const(char)[] sliceNumber()
+    const(char)[] sliceNumber() return scope
     {
         debug(trace) printf( "sliceNumber+\n" );
         debug(trace) scope(success) printf( "sliceNumber-\n" );
@@ -449,7 +448,7 @@ pure @safe:
     }
 
 
-    size_t decodeNumber()
+    size_t decodeNumber() scope
     {
         debug(trace) printf( "decodeNumber+\n" );
         debug(trace) scope(success) printf( "decodeNumber-\n" );
@@ -458,7 +457,7 @@ pure @safe:
     }
 
 
-    size_t decodeNumber( const(char)[] num )
+    size_t decodeNumber( scope const(char)[] num ) scope
     {
         debug(trace) printf( "decodeNumber+\n" );
         debug(trace) scope(success) printf( "decodeNumber-\n" );
@@ -479,7 +478,7 @@ pure @safe:
     }
 
 
-    void parseReal()
+    void parseReal() scope
     {
         debug(trace) printf( "parseReal+\n" );
         debug(trace) scope(success) printf( "parseReal-\n" );
@@ -570,7 +569,7 @@ pure @safe:
         Namechar
         Namechar Namechars
     */
-    void parseLName()
+    void parseLName() scope
     {
         debug(trace) printf( "parseLName+\n" );
         debug(trace) scope(success) printf( "parseLName-\n" );
@@ -788,7 +787,7 @@ pure @safe:
     TypeTuple:
         B Number Arguments
     */
-    char[] parseType( char[] name = null )
+    char[] parseType( char[] name = null ) return scope
     {
         static immutable string[23] primitives = [
             "char", // a
@@ -924,7 +923,6 @@ pure @safe:
             return dst[beg .. len];
         case 'F': case 'U': case 'W': case 'V': case 'R': // TypeFunction
             return parseTypeFunction( name );
-        case 'I': // TypeIdent (I LName)
         case 'C': // TypeClass (C LName)
         case 'S': // TypeStruct (S LName)
         case 'E': // TypeEnum (E LName)
@@ -1186,13 +1184,17 @@ pure @safe:
                 popFront();
                 put( "scope " );
                 continue;
+            case 'm': // FuncAttrLive
+                popFront();
+                put( "@live " );
+                continue;
             default:
                 error();
             }
         }
     }
 
-    void parseFuncArguments()
+    void parseFuncArguments() scope
     {
         // Arguments
         for ( size_t n = 0; true; n++ )
@@ -1233,9 +1235,11 @@ pure @safe:
             }
             switch ( front )
             {
-            case 'J': // out (J Type)
+            case 'I': // in  (I Type)
                 popFront();
-                put( "out " );
+                put("in ");
+                if (front == 'K')
+                    goto case;
                 parseType();
                 continue;
             case 'K': // ref (K Type)
@@ -1243,6 +1247,11 @@ pure @safe:
                 put( "ref " );
                 parseType();
                 continue;
+            case 'J': // out (J Type)
+                popFront();
+                put( "out " );
+                parseType();
+                continue;
             case 'L': // lazy (L Type)
                 popFront();
                 put( "lazy " );
@@ -1260,7 +1269,7 @@ pure @safe:
         TypeFunction:
             CallConvention FuncAttrs Arguments ArgClose Type
     */
-    char[] parseTypeFunction( char[] name = null, IsDelegate isdg = IsDelegate.no )
+    char[] parseTypeFunction( char[] name = null, IsDelegate isdg = IsDelegate.no ) return
     {
         debug(trace) printf( "parseTypeFunction+\n" );
         debug(trace) scope(success) printf( "parseTypeFunction-\n" );
@@ -1349,7 +1358,7 @@ pure @safe:
         E
         F
     */
-    void parseValue( char[] name = null, char type = '\0' )
+    void parseValue(scope  char[] name = null, char type = '\0' ) scope
     {
         debug(trace) printf( "parseValue+\n" );
         debug(trace) scope(success) printf( "parseValue-\n" );
@@ -1464,13 +1473,19 @@ pure @safe:
             }
             put( ')' );
             return;
+        case 'f':
+            // f MangledName
+            // A function literal symbol
+            popFront();
+            parseMangledName(false, 1);
+            return;
         default:
             error();
         }
     }
 
 
-    void parseIntegerValue( char[] name = null, char type = '\0' )
+    void parseIntegerValue( scope char[] name = null, char type = '\0' ) scope
     {
         debug(trace) printf( "parseIntegerValue+\n" );
         debug(trace) scope(success) printf( "parseIntegerValue-\n" );
@@ -1580,7 +1595,7 @@ pure @safe:
         S Number_opt QualifiedName
         X ExternallyMangledName
     */
-    void parseTemplateArgs()
+    void parseTemplateArgs() scope
     {
         debug(trace) printf( "parseTemplateArgs+\n" );
         debug(trace) scope(success) printf( "parseTemplateArgs-\n" );
@@ -1608,7 +1623,7 @@ pure @safe:
                 char t = front; // peek at type for parseValue
                 if ( t == 'Q' )
                     t = peekBackref();
-                char[] name; silent( name = parseType() );
+                char[] name; silent( delegate void() { name = parseType(); } );
                 parseValue( name, t );
                 continue;
             case 'S':
@@ -1714,7 +1729,7 @@ pure @safe:
     TemplateInstanceName:
         Number __T LName TemplateArgs Z
     */
-    void parseTemplateInstanceName(bool hasNumber)
+    void parseTemplateInstanceName(bool hasNumber) scope
     {
         debug(trace) printf( "parseTemplateInstanceName+\n" );
         debug(trace) scope(success) printf( "parseTemplateInstanceName-\n" );
@@ -1739,7 +1754,7 @@ pure @safe:
     }
 
 
-    bool mayBeTemplateInstanceName()
+    bool mayBeTemplateInstanceName() scope
     {
         debug(trace) printf( "mayBeTemplateInstanceName+\n" );
         debug(trace) scope(success) printf( "mayBeTemplateInstanceName-\n" );
@@ -1759,7 +1774,7 @@ pure @safe:
         LName
         TemplateInstanceName
     */
-    void parseSymbolName()
+    void parseSymbolName() scope
     {
         debug(trace) printf( "parseSymbolName+\n" );
         debug(trace) scope(success) printf( "parseSymbolName-\n" );
@@ -1801,7 +1816,7 @@ pure @safe:
 
     // parse optional function arguments as part of a symbol name, i.e without return type
     // if keepAttr, the calling convention and function attributes are not discarded, but returned
-    char[] parseFunctionTypeNoReturn( bool keepAttr = false )
+    char[] parseFunctionTypeNoReturn( bool keepAttr = false ) return scope
     {
         // try to demangle a function, in case we are pointing to some function local
         auto prevpos = pos;
@@ -1852,7 +1867,7 @@ pure @safe:
         SymbolName
         SymbolName QualifiedName
     */
-    char[] parseQualifiedName()
+    char[] parseQualifiedName() return scope
     {
         debug(trace) printf( "parseQualifiedName+\n" );
         debug(trace) scope(success) printf( "parseQualifiedName-\n" );
@@ -1876,7 +1891,7 @@ pure @safe:
         _D QualifiedName Type
         _D QualifiedName M Type
     */
-    void parseMangledName( bool displayType, size_t n = 0 )
+    void parseMangledName( bool displayType, size_t n = 0 ) scope
     {
         debug(trace) printf( "parseMangledName+\n" );
         debug(trace) scope(success) printf( "parseMangledName-\n" );
@@ -1951,7 +1966,16 @@ pure @safe:
         parseMangledName( AddType.yes == addType );
     }
 
-    char[] doDemangle(alias FUNC)()
+    char[] copyInput() return scope
+    {
+        if (dst.length < buf.length)
+            dst.length = buf.length;
+        char[] r = dst[0 .. buf.length];
+        r[] = buf[];
+        return r;
+    }
+
+    char[] doDemangle(alias FUNC)() return scope
     {
         while ( true )
         {
@@ -1979,10 +2003,7 @@ pure @safe:
                     auto msg = e.toString();
                     printf( "error: %.*s\n", cast(int) msg.length, msg.ptr );
                 }
-                if ( dst.length < buf.length )
-                    dst.length = buf.length;
-                dst[0 .. buf.length] = buf[];
-                return dst[0 .. buf.length];
+                return copyInput();
             }
             catch ( Exception e )
             {
@@ -2015,10 +2036,13 @@ pure @safe:
  *  The demangled name or the original string if the name is not a mangled D
  *  name.
  */
-char[] demangle( const(char)[] buf, char[] dst = null ) nothrow pure @safe
+char[] demangle(return scope const(char)[] buf, return scope char[] dst = null ) nothrow pure @safe
 {
-    //return Demangle(buf, dst)();
     auto d = Demangle!()(buf, dst);
+    // fast path (avoiding throwing & catching exception) for obvious
+    // non-D mangled names
+    if (buf.length < 2 || !(buf[0] == 'D' || buf[0..2] == "_D"))
+        return d.copyInput();
     return d.demangleName();
 }
 
@@ -2051,7 +2075,7 @@ char[] demangleType( const(char)[] buf, char[] dst = null ) nothrow pure @safe
 * Returns:
 *  The mangled name with deduplicated identifiers
 */
-char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
+char[] reencodeMangled(return scope const(char)[] mangled) nothrow pure @safe
 {
     static struct PrependHooks
     {
@@ -2067,7 +2091,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
         Replacement [] replacements;
 
     pure @safe:
-        size_t positionInResult(size_t pos)
+        size_t positionInResult(size_t pos) scope
         {
             foreach_reverse (r; replacements)
                 if (pos >= r.pos)
@@ -2077,7 +2101,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
 
         alias Remangle = Demangle!(PrependHooks);
 
-        void flushPosition(ref Remangle d)
+        void flushPosition(ref Remangle d) scope
         {
             if (lastpos < d.pos)
             {
@@ -2096,7 +2120,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
             }
         }
 
-        bool parseLName(ref Remangle d)
+        bool parseLName(scope ref Remangle d) scope
         {
             flushPosition(d);
 
@@ -2127,7 +2151,8 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
                     npos = positionInResult(*pid);
                 }
                 encodeBackref(reslen - npos);
-                replacements ~= Replacement(d.pos, result.length);
+                const pos = d.pos; // work around issues.dlang.org/show_bug.cgi?id=20675
+                replacements ~= Replacement(pos, result.length);
             }
             else
             {
@@ -2141,7 +2166,8 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
                     size_t npos = positionInResult(*pid);
                     result.length = reslen;
                     encodeBackref(reslen - npos);
-                    replacements ~= Replacement(d.pos, result.length);
+                    const pos = d.pos; // work around issues.dlang.org/show_bug.cgi?id=20675
+                    replacements ~= Replacement(pos, result.length);
                 }
                 else
                 {
@@ -2153,7 +2179,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
             return true;
         }
 
-        char[] parseType( ref Remangle d, char[] name = null )
+        char[] parseType( ref Remangle d, char[] name = null ) return scope
         {
             if (d.front != 'Q')
                 return null;
@@ -2174,7 +2200,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
             return result[reslen .. $]; // anything but null
         }
 
-        void encodeBackref(size_t relpos)
+        void encodeBackref(size_t relpos) scope
         {
             result ~= 'Q';
             enum base = 26;
@@ -2221,7 +2247,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
  *  The mangled name for a symbols of type T and the given fully
  *  qualified name.
  */
-char[] mangle(T)(const(char)[] fqn, char[] dst = null) @safe pure nothrow
+char[] mangle(T)(return scope const(char)[] fqn, return scope char[] dst = null) @safe pure nothrow
 {
     import core.internal.string : numDigits, unsignedToTempString;
 
@@ -2232,19 +2258,19 @@ char[] mangle(T)(const(char)[] fqn, char[] dst = null) @safe pure nothrow
 
         @property bool empty() const { return !s.length; }
 
-        @property const(char)[] front() const
+        @property const(char)[] front() const return
         {
             immutable i = indexOfDot();
             return i == -1 ? s[0 .. $] : s[0 .. i];
         }
 
-        void popFront()
+        void popFront() scope
         {
             immutable i = indexOfDot();
             s = i == -1 ? s[$ .. $] : s[i+1 .. $];
         }
 
-        private ptrdiff_t indexOfDot() const
+        private ptrdiff_t indexOfDot() const scope
         {
             foreach (i, c; s) if (c == '.') return i;
             return -1;
@@ -2311,7 +2337,7 @@ char[] mangle(T)(const(char)[] fqn, char[] dst = null) @safe pure nothrow
  *  The mangled name for a function with function pointer type T and
  *  the given fully qualified name.
  */
-char[] mangleFunc(T:FT*, FT)(const(char)[] fqn, char[] dst = null) @safe pure nothrow if (is(FT == function))
+char[] mangleFunc(T:FT*, FT)(return scope const(char)[] fqn, return scope char[] dst = null) @safe pure nothrow if (is(FT == function))
 {
     static if (isExternD!FT)
     {
@@ -2335,7 +2361,6 @@ char[] mangleFunc(T:FT*, FT)(const(char)[] fqn, char[] dst = null) @safe pure no
 
 private enum hasTypeBackRef = (int function(void**,void**)).mangleof[$-4 .. $] == "QdZi";
 
-///
 @safe pure nothrow unittest
 {
     assert(mangleFunc!(int function(int))("a.b") == "_D1a1bFiZi");
@@ -2412,13 +2437,15 @@ else version (Darwin)
 else
     enum string cPrefix = "";
 
-version (unittest)
+@safe pure nothrow unittest
 {
     immutable string[2][] table =
     [
         ["printf", "printf"],
         ["_foo", "_foo"],
         ["_D88", "_D88"],
+        ["_D3fooQeFIAyaZv", "void foo.foo(in immutable(char)[])" ],
+        ["_D3barQeFIKAyaZv", "void bar.bar(in ref immutable(char)[])" ],
         ["_D4test3fooAa", "char[] test.foo"],
         ["_D8demangle8demangleFAaZAa", "char[] demangle.demangle(char[])"],
         ["_D6object6Object8opEqualsFC6ObjectZi", "int object.Object.opEquals(Object)"],
@@ -2470,7 +2497,7 @@ version (unittest)
         ["_D3foo7__arrayZ", "foo.__array"],
         ["_D8link657428__T3fooVE8link65746Methodi0Z3fooFZi", "int link6574.foo!(0).foo()"],
         ["_D8link657429__T3fooHVE8link65746Methodi0Z3fooFZi", "int link6574.foo!(0).foo()"],
-        ["_D4test22__T4funcVAyaa3_610a62Z4funcFNaNbNiNfZAya", `pure nothrow @nogc @safe immutable(char)[] test.func!("a\x0ab").func()`],
+        ["_D4test22__T4funcVAyaa3_610a62Z4funcFNaNbNiNmNfZAya", `pure nothrow @nogc @live @safe immutable(char)[] test.func!("a\x0ab").func()`],
         ["_D3foo3barFzkZzi", "cent foo.bar(ucent)"],
         ["_D5bug145Class3fooMFNlZPv", "scope void* bug14.Class.foo()"],
         ["_D5bug145Class3barMFNjZPv", "return void* bug14.Class.bar()"],
@@ -2482,6 +2509,8 @@ version (unittest)
          "pure @safe int std.format.getNth!(\"integer width\", std.traits.isIntegral, int, uint, uint).getNth(uint, uint, uint)"],
         ["_D3std11parallelism42__T16RoundRobinBufferTDFKAaZvTDxFNaNdNeZbZ16RoundRobinBuffer5primeMFZv",
          "void std.parallelism.RoundRobinBuffer!(void delegate(ref char[]), bool delegate() pure @property @trusted const).RoundRobinBuffer.prime()"],
+        ["_D6mangle__T8fun21753VSQv6S21753S1f_DQBj10__lambda71MFNaNbNiNfZvZQCbQp",
+        "void function() pure nothrow @nogc @safe mangle.fun21753!(mangle.S21753(mangle.__lambda71())).fun21753"],
         // Lname '0'
         ["_D3std9algorithm9iteration__T9MapResultSQBmQBlQBe005stripTAAyaZQBi7opSliceMFNaNbNiNfmmZSQDiQDhQDa__TQCtSQDyQDxQDq00QCmTQCjZQDq",
          "pure nothrow @nogc @safe std.algorithm.iteration.MapResult!(std.algorithm.iteration.__anonymous.strip, "
@@ -2541,23 +2570,56 @@ version (unittest)
         else
             alias staticIota = Seq!(staticIota!(x - 1), x - 1);
     }
-}
-@safe pure nothrow unittest
-{
     foreach ( i, name; table )
     {
         auto r = demangle( name[0] );
         assert( r == name[1],
-                "demangled \"" ~ name[0] ~ "\" as \"" ~ r ~ "\" but expected \"" ~ name[1] ~ "\"");
+                "demangled `" ~ name[0] ~ "` as `" ~ r ~ "` but expected `" ~ name[1] ~ "`");
     }
     foreach ( i; staticIota!(table.length) )
     {
         enum r = demangle( table[i][0] );
         static assert( r == table[i][1],
-                "demangled \"" ~ table[i][0] ~ "\" as \"" ~ r ~ "\" but expected \"" ~ table[i][1] ~ "\"");
+                "demangled `" ~ table[i][0] ~ "` as `" ~ r ~ "` but expected `" ~ table[i][1] ~ "`");
+    }
+
+    {
+        // https://issues.dlang.org/show_bug.cgi?id=18531
+        auto symbol = `_D3std3uni__T6toCaseS_DQvQt12toLowerIndexFNaNbNiNewZtVii1043S_DQCjQCi10toLowerTabFNaNbNiNemZwSQDo5ascii7toLowerTAyaZQDzFNaNeQmZ14__foreachbody2MFNaNeKmKwZ14__foreachbody3MFNaNeKwZi`;
+        auto demangled = `pure @trusted int std.uni.toCase!(std.uni.toLowerIndex(dchar), 1043, std.uni.toLowerTab(ulong), std.ascii.toLower, immutable(char)[]).toCase(immutable(char)[]).__foreachbody2(ref ulong, ref dchar).__foreachbody3(ref dchar)`;
+        auto dst = new char[200];
+        auto ret = demangle( symbol, dst);
+        assert( ret == demangled );
     }
 }
 
+unittest
+{
+    // https://issues.dlang.org/show_bug.cgi?id=18300
+    string s = demangle.mangleof;
+    foreach (i; 1..77)
+    {
+        char[] buf = new char[i];
+        auto ds = demangle(s, buf);
+        assert(ds == "pure nothrow @safe char[] core.demangle.demangle(scope return const(char)[], scope return char[])" ||
+               ds == "pure nothrow @safe char[] core.demangle.demangle(return scope const(char)[], return scope char[])");
+    }
+}
+
+unittest
+{
+    // https://issues.dlang.org/show_bug.cgi?id=18300
+    string s = "_D1";
+    string expected = "int ";
+    foreach (_; 0..10_000)
+    {
+        s ~= "a1";
+        expected ~= "a.";
+    }
+    s ~= "FiZi";
+    expected ~= "F";
+    assert(s.demangle == expected);
+}
 
 /*
  *