Test case:
void main() nothrow
{
throw new Exception("");
version(A) asm { nop; }
}
Without -version=A, the error "Exception is thrown but not caught" is properly reported. But with -version=A, no error occurs.
Comment #1 by k.hara.pg — 2014-06-29T06:19:25Z
Copy my comment from https://issues.dlang.org/show_bug.cgi?id=11471#c6
-----
The root issue is in FuncDeclaration::semantic3.
...
else if (hasReturnExp & 8) // if inline asm
{
flags &= ~FUNCFLAGnothrowInprocess;
}
else
{
// Check for errors related to 'nothrow'.
unsigned int nothrowErrors = global.errors;
int blockexit = fbody->blockExit(this, f->isnothrow);
if (f->isnothrow && (global.errors != nothrowErrors) )
::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars());
...
In front-end, if a function body has inline asm statements, the function's nothrow check is skipped! But many functions in druntime rely on the loose behavior currently.
Finally I thought that the following semantic would be pragmatic.
By default, inline assembler statement is handled as impure, unsafe, throwable, and gc-able.
void f()() { asm { nop; } }
pragma(msg, typeof(&f!()));
// will print 'void function() @system'
But, explicit annotating with 'pure', 'nothrow', '@trusted', and '@nogc' will be able to override the behavior.
void f2()() pure nothrow @trusted @nogc { asm { nop; } }
pragma(msg, typeof(&f2!()));
// will print 'void function() pure nothrow @trusted @nogc'
And still, inline assembler is unsafe, so it will conflict wiht '@safe' attribute.
void f3()() @safe { asm { nop; } }
pragma(msg, typeof(&f3!()));
// Error: inline assembler not allowed in @safe function f!().f
Comment #5 by github-bugzilla — 2014-10-06T13:05:31Z