Wolfgang Thallergcc16 merge934c3885 months agoHistory
1004 lines · 29.8 KB · D
RawDownload
/**    The exception module defines all system-level exceptions and provides a    mechanism to alter system-level error handling.     Copyright: Copyright Sean Kelly 2005 - 2013.    License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).    Authors:   Sean Kelly and $(HTTP jmdavisprog.com, Jonathan M Davis)    Source:    $(DRUNTIMESRC core/_exception.d) */module core.exception; // Compiler lowers final switch default case to this (which is a runtime error)void __switch_errorT()(string file = __FILE__, size_t line = __LINE__) @trusted{    // Consider making this a compile time check.    version (D_Exceptions)        throw staticError!SwitchError("No appropriate switch clause found", file, line, null);    else        assert(0, "No appropriate switch clause found");} /* * Make sure template __switch_errorT is always instantiated when building * druntime. This works around https://issues.dlang.org/show_bug.cgi?id=20802. * When druntime and phobos are compiled with -release, the instance for * __switch_errorT is not needed. An application compiled with -release * could need the instance for __switch_errorT, but the compiler would * not generate code for it, because it assumes, that it was already * generated for druntime. Always including the instance in a compiled * druntime allows to use an application without -release with druntime * with -release. */private alias dummy__switch_errorT = __switch_errorT!(); /** * Thrown on a range error. */class RangeError : Error{    this( string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @nogc nothrow pure @safe    {        super( "Range violation", file, line, next );    }     protected this( string msg, string file, size_t line, Throwable next = null ) @nogc nothrow pure @safe    {        super( msg, file, line, next );    }} unittest{    {        auto re = new RangeError();        assert(re.file == __FILE__);        assert(re.line == __LINE__ - 2);        assert(re.next is null);        assert(re.msg == "Range violation");    }     {        auto re = new RangeError("hello", 42, new Exception("It's an Exception!"));        assert(re.file == "hello");        assert(re.line == 42);        assert(re.next !is null);        assert(re.msg == "Range violation");    }} /** * Thrown when an out of bounds array index is accessed. */class ArrayIndexError : RangeError{    /// Index into array    const size_t index;    /// Length of indexed array    const size_t length;     // Buffer to avoid GC allocations    private immutable char[100] msgBuf = '\0';     this(size_t index, size_t length, string file = __FILE__,         size_t line = __LINE__, Throwable next = null) @nogc nothrow pure @safe    {        this.index  = index;        this.length = length;         // Constructing the message is a bit clumsy:        // It's essentially `printf("index [%zu] is out of bounds for array of length [%zu]", index, length)`,        // but even `snprintf` isn't `pure`.        // Also string concatenation isn't `@nogc`, and casting to/from immutable isn't `@safe`        import core.internal.string : unsignedToTempString;        char[msgBuf.length] buf = void;        char[20] tmpBuf = void;        char[] sink = buf[];        sink.rangeMsgPut("index [");        sink.rangeMsgPut(unsignedToTempString!10(index, tmpBuf));        sink.rangeMsgPut("] is out of bounds for array of length ");        sink.rangeMsgPut(unsignedToTempString!10(length, tmpBuf));        this.msgBuf = buf;        super(msgBuf[0..$-sink.length], file, line, next);    }} @safe pure unittest{    assert(new ArrayIndexError(900, 700).msg == "index [900] is out of bounds for array of length 700");    // Ensure msg buffer doesn't overflow on large numbers    assert(new ArrayIndexError(size_t.max, size_t.max-1).msg);} unittest{    try    {        _d_arraybounds_indexp("test", 400, 9, 3);        assert(0, "no ArrayIndexError thrown");    }    catch (ArrayIndexError re)    {        assert(re.file   == "test");        assert(re.line   == 400);        assert(re.index  == 9);        assert(re.length == 3);    }} /** * Thrown when an out of bounds array slice is created */class ArraySliceError : RangeError{    /// Lower/upper bound passed to slice: `array[lower .. upper]`    const size_t lower, upper;    /// Length of sliced array    const size_t length;     private immutable char[120] msgBuf = '\0';     this(size_t lower, size_t upper, size_t length, string file = __FILE__,         size_t line = __LINE__, Throwable next = null) @nogc nothrow pure @safe    {        this.lower  = lower;        this.upper  = upper;        this.length = length;         // Constructing the message is a bit clumsy for the same reasons as ArrayIndexError        import core.internal.string : unsignedToTempString;        char[msgBuf.length] buf = void;        char[20] tmpBuf = void;        char[] sink = buf;        sink.rangeMsgPut("slice [");        sink.rangeMsgPut(unsignedToTempString!10(lower, tmpBuf));        sink.rangeMsgPut(" .. ");        sink.rangeMsgPut(unsignedToTempString!10(upper, tmpBuf));        sink.rangeMsgPut("] ");        if (lower > upper)        {            sink.rangeMsgPut("has a larger lower index than upper index");        }        else        {            sink.rangeMsgPut("extends past source array of length ");            sink.rangeMsgPut(unsignedToTempString!10(length, tmpBuf));        }         this.msgBuf = buf;        super(msgBuf[0..$-sink.length], file, line, next);    }} @safe pure unittest{    assert(new ArraySliceError(40, 80, 20).msg == "slice [40 .. 80] extends past source array of length 20");    assert(new ArraySliceError(90, 70, 20).msg == "slice [90 .. 70] has a larger lower index than upper index");    // Ensure msg buffer doesn't overflow on large numbers    assert(new ArraySliceError(size_t.max, size_t.max, size_t.max-1).msg);} unittest{    try    {        _d_arraybounds_slicep("test", 400, 1, 7, 3);        assert(0, "no ArraySliceError thrown");    }    catch (ArraySliceError re)    {        assert(re.file   == "test");        assert(re.line   == 400);        assert(re.lower  == 1);        assert(re.upper  == 7);        assert(re.length == 3);    }} /// Mini `std.range.primitives: put` for constructor of ArraySliceError / ArrayIndexErrorprivate void rangeMsgPut(ref char[] r, scope const(char)[] e) @nogc nothrow pure @safe{    assert(r.length >= e.length); // don't throw ArraySliceError inside ArrayIndexError ctor    r[0 .. e.length] = e[];    r = r[e.length .. $];} /** * Thrown on an assert error. */class AssertError : Error{    @safe pure nothrow @nogc this( string file, size_t line )    {        this(cast(Throwable)null, file, line);    }     @safe pure nothrow @nogc this( Throwable next, string file = __FILE__, size_t line = __LINE__ )    {        this( "Assertion failure", file, line, next);    }     @safe pure nothrow @nogc this( string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null )    {        super( msg, file, line, next );    }} unittest{    {        auto ae = new AssertError("hello", 42);        assert(ae.file == "hello");        assert(ae.line == 42);        assert(ae.next is null);        assert(ae.msg == "Assertion failure");    }     {        auto ae = new AssertError(new Exception("It's an Exception!"));        assert(ae.file == __FILE__);        assert(ae.line == __LINE__ - 2);        assert(ae.next !is null);        assert(ae.msg == "Assertion failure");    }     {        auto ae = new AssertError(new Exception("It's an Exception!"), "hello", 42);        assert(ae.file == "hello");        assert(ae.line == 42);        assert(ae.next !is null);        assert(ae.msg == "Assertion failure");    }     {        auto ae = new AssertError("msg");        assert(ae.file == __FILE__);        assert(ae.line == __LINE__ - 2);        assert(ae.next is null);        assert(ae.msg == "msg");    }     {        auto ae = new AssertError("msg", "hello", 42);        assert(ae.file == "hello");        assert(ae.line == 42);        assert(ae.next is null);        assert(ae.msg == "msg");    }     {        auto ae = new AssertError("msg", "hello", 42, new Exception("It's an Exception!"));        assert(ae.file == "hello");        assert(ae.line == 42);        assert(ae.next !is null);        assert(ae.msg == "msg");    }} /** * When an unmapped pointer is accessed this may be thrown via a signal handler. */class InvalidPointerError : Error{    @safe pure nothrow @nogc this(string file, size_t line)    {        this(file, line, cast(Throwable)null);    }     @safe pure nothrow @nogc this(string file = __FILE__, size_t line = __LINE__, Throwable next = null)    {        this("Invalid pointer access", file, line, next);    }     @safe pure nothrow @nogc this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)    {        super(msg, file, line, next);    }} /** * Thrown when a null dereference may occur. * * Depends upon null dereference check, or a signal handler to throw. */class NullPointerError : InvalidPointerError{    @safe pure nothrow @nogc this(string file, size_t line)    {        this(file, line, cast(Throwable)null);    }     @safe pure nothrow @nogc this(string file = __FILE__, size_t line = __LINE__, Throwable next = null)    {        this("Null pointer dereference", file, line, next);    }     @safe pure nothrow @nogc this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)    {        super(msg, file, line, next);    }} /** * Thrown on finalize error. */class FinalizeError : Error{    TypeInfo   info;     this( TypeInfo ci, Throwable next, string file = __FILE__, size_t line = __LINE__ ) @safe pure nothrow @nogc    {        this(ci, file, line, next);    }     this( TypeInfo ci, string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc    {        super( "Finalization error", file, line, next );        info = ci;    }     override string toString() const @safe    {        return "An exception was thrown while finalizing an instance of " ~ info.toString();    }} unittest{    ClassInfo info = new ClassInfo;    info.name = "testInfo";     {        auto fe = new FinalizeError(info);        assert(fe.file == __FILE__);        assert(fe.line == __LINE__ - 2);        assert(fe.next is null);        assert(fe.msg == "Finalization error");        assert(fe.info == info);    }     {        auto fe = new FinalizeError(info, new Exception("It's an Exception!"));        assert(fe.file == __FILE__);        assert(fe.line == __LINE__ - 2);        assert(fe.next !is null);        assert(fe.msg == "Finalization error");        assert(fe.info == info);    }     {        auto fe = new FinalizeError(info, "hello", 42);        assert(fe.file == "hello");        assert(fe.line == 42);        assert(fe.next is null);        assert(fe.msg == "Finalization error");        assert(fe.info == info);    }     {        auto fe = new FinalizeError(info, "hello", 42, new Exception("It's an Exception!"));        assert(fe.file == "hello");        assert(fe.line == 42);        assert(fe.next !is null);        assert(fe.msg == "Finalization error");        assert(fe.info == info);    }} /** * Thrown on an out of memory error. */class OutOfMemoryError : Error{    this(string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc    {        this(true, file, line, next);    }     this(bool trace, string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc    {        super("Memory allocation failed", file, line, next);        if (!trace)            this.info = SuppressTraceInfo.instance;    }     override string toString() const @trusted    {        return msg.length ? (cast()this).superToString() : "Memory allocation failed";    }     // kludge to call non-const super.toString    private string superToString() @trusted    {        return super.toString();    }} unittest{    {        auto oome = new OutOfMemoryError();        assert(oome.file == __FILE__);        assert(oome.line == __LINE__ - 2);        assert(oome.next is null);        assert(oome.msg == "Memory allocation failed");        assert(oome.toString.length);    }     {        auto oome = new OutOfMemoryError("hello", 42, new Exception("It's an Exception!"));        assert(oome.file == "hello");        assert(oome.line == 42);        assert(oome.next !is null);        assert(oome.msg == "Memory allocation failed");    }}  /** * Thrown on an invalid memory operation. * * An invalid memory operation error occurs in circumstances when the garbage * collector has detected an operation it cannot reliably handle. The default * D GC is not re-entrant, so this can happen due to allocations done from * within finalizers called during a garbage collection cycle. */class InvalidMemoryOperationError : Error{    this(string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc    {        super( "Invalid memory operation", file, line, next );    }     override string toString() const @trusted    {        return msg.length ? (cast()this).superToString() : "Invalid memory operation";    }     // kludge to call non-const super.toString    private string superToString() @trusted    {        return super.toString();    }} unittest{    {        auto oome = new InvalidMemoryOperationError();        assert(oome.file == __FILE__);        assert(oome.line == __LINE__ - 2);        assert(oome.next is null);        assert(oome.msg == "Invalid memory operation");        assert(oome.toString.length);    }     {        auto oome = new InvalidMemoryOperationError("hello", 42, new Exception("It's an Exception!"));        assert(oome.file == "hello");        assert(oome.line == 42);        assert(oome.next !is null);        assert(oome.msg == "Invalid memory operation");    }}  /*** Thrown on a configuration error.*/class ForkError : Error{    this( string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @nogc nothrow pure @safe    {        super( "fork() failed", file, line, next );    }}  /** * Thrown on a switch error. */

Lines 1–500 of 1004.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t