Showing with 34 additions and 1 deletion.
  1. +3 −1 src/statement.c
  2. +31 −0 test/compilable/test14747.d
4 changes: 3 additions & 1 deletion src/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,9 @@ int Statement::blockExit(FuncDeclaration *func, bool mustNotThrow)
if (s)
{
int r = s->blockExit(func, mustNotThrow);
result |= r & ~(BEbreak | BEcontinue);
result |= r & ~(BEbreak | BEcontinue | BEfallthru);
if ((r & (BEfallthru | BEcontinue | BEbreak)) == 0)
result &= ~BEfallthru;
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions test/compilable/test14747.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// REQUIRED_ARGS: -o-
// PERMUTE_ARGS: -w

int foo(Args...)()
{
int x;

foreach (arg; Args)
{
static if(is(arg == int))
{
return 0;
}
static if(is(arg == long))
{
// fallthrough
++x; // this statement might be unreachable, but
// UnrollStatement does not warn that.
}
}
// no return
}

void main()
{
auto r1 = foo!(int)(); // return
auto r2 = foo!(int, long)(); // return -> fallthrough (it's unreachable)
auto r3 = foo!(long, int)(); // fallthough -> return
static assert(!__traits(compiles, foo!(long)())); // fallthough
static assert(!__traits(compiles, foo!(long, long)())); // fallthough -> fallthough
}