The assignment operators for the built in types return an lvalue in C++ (unlike in C). But you cannot use it to modify the object without an intervening sequence point, so your example is undefined behavior (in C++03—C++11 changed a lot here, and I seem to remember that one of the results made your code defined).
Regardless of the situation with regards to undefined behavior, you would be better off writing:
x = 2 * x + y;
It's far more readable. The fact that the assignment operators result in lvalues is really only usable when the results are bound immediately to a reference:
T&
SomeClass::f()
{
// ...
return aTinSomeClass += 42;
}
And even then, I'd write it in two statements.
(The general rule in C++ is that if the result of an operator corresponds to the value of an object in memory, then it is an lvalue. There was no general rule in C.)