Index: expression.c
===================================================================
--- expression.c	(revision 304)
+++ expression.c	(working copy)
@@ -9861,31 +9861,86 @@
     if ( (e1->type->isintegral() || e1->type->isfloating()) &&
 	 (e2->type->isintegral() || e2->type->isfloating()))
     {
-	// For built-in numeric types, there are three cases:
-	// x ^^ 1   ----> x
-	// x ^^ 0.5 ----> sqrt(x)
-	// x ^^ y   ----> pow(x, y)
+	// For built-in numeric types, there are several cases.
 	// TODO: backend support, especially for  e1 ^^ 2.
+
 	bool wantSqrt = false;	
 	e2 = e2->optimize(0);
-	if ((e2->op == TOKfloat64 && e2->toReal() == 1.0) ||
-	    (e2->op == TOKint64 && e2->toInteger() == 1))
+	e1 = e1->optimize(0);
+	
+	// Replace 1 ^^ x or 1.0^^x by (x, 1)
+	if ((e1->op == TOKint64 && e1->toInteger() == 1) ||
+		(e1->op == TOKfloat64 && e1->toReal() == 1.0))
 	{
-	    return e1;  // Replace x ^^ 1 with x.
+	    typeCombine(sc);
+	    e = new CommaExp(loc, e2, e1);
+	    e = e->semantic(sc);
+	    return e;
 	}
+	// Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral
+	if ( e2->type->isintegral() && e1->op == TOKint64 && (long long)e1->toInteger() == -1L)
+	{
+	    typeCombine(sc);
+	    Type * resultType = type;
+	    e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2->type));
+	    e = new CondExp(loc, e, new IntegerExp(loc, -1L, resultType), new IntegerExp(loc, 1L, resultType));
+	    e = e->semantic(sc);
+	    return e;
+	}
+	// All other negative integral powers are illegal
+	if ((e1->type->isintegral()) && (e2->op == TOKint64) && (long long)(e2->toInteger())< 0)
+	{
+	    error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?",
+		e1->type->toBasetype()->toChars(), e1->toChars(), e2->toChars());
+	    return new ErrorExp();
+	}
+	
+	// Deal with x^^2, x^^3 immediately, since they are of practical importance.
+	// Don't bother if x is a literal, since it will be constant-folded anyway.
+	if ( (  (e2->op == TOKint64 && (e2->toInteger() == 2 || e2->toInteger() == 3)) 
+	     ||	(e2->op == TOKfloat64 && (e2->toReal() == 2.0 || e2->toReal() == 3.0))
+	     ) && e1->op !=TOKint64 && e1->op!=TOKfloat64
+	   )
+	{
+	    typeCombine(sc);
+	    // Replace x^^2 with (tmp = x, tmp*tmp)
+	    // Replace x^^3 with (tmp = x, tmp*tmp*tmp) 
+	    Identifier *idtmp = Lexer::uniqueId("__tmp");
+	    VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(0, e1));
+	    VarExp * ve = new VarExp(loc, tmp);
+	    Expression *ae = new DeclarationExp(loc, tmp);
+	    Expression *me = new MulExp(loc, ve, ve);
+	    if ( (e2->op == TOKint64 && e2->toInteger() == 3) 
+	      || (e2->op == TOKfloat64 && e2->toReal() == 3.0))
+		me = new MulExp(loc, me, ve);
+	    e = new CommaExp(loc, ae, me);
+	    e = e->semantic(sc);
+	    return e;
+	}
 
 	e = new IdentifierExp(loc, Id::empty);
 	e = new DotIdExp(loc, e, Id::std);
 	e = new DotIdExp(loc, e, Id::math);
 	if (e2->op == TOKfloat64 && e2->toReal() == 0.5)
 	{   // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
+	    typeCombine(sc);
 	    e = new CallExp(loc, new DotIdExp(loc, e, Id::_sqrt), e1);
 	}
 	else 
-	{   // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
- 	    e = new CallExp(loc, new DotIdExp(loc, e, Id::_pow), e1, e2);	
+	{
+	    // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
+	    // We don't combine the types if raising to an integer power (because
+	    // integer powers are treated specially by std.math.pow).
+	    if (!e2->type->isintegral())
+		typeCombine(sc);
+	    e = new CallExp(loc, new DotIdExp(loc, e, Id::_pow), e1, e2);	
 	}	
 	e = e->semantic(sc);
+	// Always constant fold integer powers of literals. This will run the interpreter
+	// on .std.math.pow
+	if ((e1->op == TOKfloat64 || e1->op == TOKint64) && (e2->op == TOKint64))
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	
 	return e;
     }
     error("%s ^^ %s is not supported", e1->type->toChars(), e2->type->toChars() );
Index: parse.c
===================================================================
--- parse.c	(revision 304)
+++ parse.c	(working copy)
@@ -5600,7 +5600,14 @@
 	    e = parsePostExp(e);
 	    break;
     }
-    assert(e);
+    assert(e);    
+    // ^^ is right associative and has higher precedence than the unary operators
+    while (token.value == TOKpow)
+    {
+	nextToken();
+	Expression *e2 = parseUnaryExp();
+	e = new PowExp(loc,e,e2);
+    }
     return e;
 }
 
@@ -5617,8 +5624,6 @@
 	    case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
 	    case TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
 	    case TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
-	    case TOKpow: nextToken(); e2 = parseUnaryExp(); e = new PowExp(loc,e,e2); continue;
-
 	    default:
 		break;
 	}
