I didn't say can't, I said didn't. llvm handles that case (which does surprise me), dmc, gcc, and vc do not. Furthermore, I'll say "cannot" on this:

            case '|':
                p++;
                if (*p == '=')
                {   p++;
                    t->value = TOKorass;
                }
                else if (*p == '|')
                {   p++;
                    t->value = TOKoror;
                }
                else
                    t->value = TOKor;
                return;

This code is correct without assuming that r is a sentinel range, and it is pretty close to your code above:

void foo(R)(ref R r, ref int tvalue)
{
    if(!r.empty)
        switch(r.front)
        {
            case '|':
                r.popFront();
                if (!r.empty && r.front == '=')
                {   r.popFront();
                    tvalue = 1;
                }
                else if (!r.empty && r.front == '|')
                {   r.popFront();
                    tvalue = 2;
                }
                else
                    tvalue = 3;
                return;
            default:
        }
}

If I add this:

struct R
{
    ubyte* p;
    @property front(){ return *p; }
    @property empty(){ return *p == 0; }
    void popFront() { p++; }
}

alias foo!R bar;

ldc2 -O3 -release compiles it to:

   0:  mov    (%rsi),%rax
   3:  cmpb   $0x7c,(%rax)
   6:  jne    3e
   8:  lea    0x1(%rax),%rcx
   c:  mov    %rcx,(%rsi)
   f:  mov    0x1(%rax),%cl
  12:  cmp    $0x7c,%cl
  15:  jne    25
  17:  add    $0x2,%rax
  1b:  mov    %rax,(%rsi)
  1e:  movl   $0x2,(%rdi)
  24:  retq
  25:  cmp    $0x3d,%cl
  28:  jne    38
  2a:  add    $0x2,%rax
  2e:  mov    %rax,(%rsi)
  31:  movl   $0x1,(%rdi)
  37:  retq
  38:  movl   $0x3,(%rdi)
  3e:  retq

Reply via email to