Implicit type conversion not always working

Arduino Language Reference states: If doing math with floats, you need to add a decimal point.
And yet, it sometimes fails.
I think everybody should be aware of this.

volatile uint32_t a = 65550;
volatile uint32_t b = 65560;

void setup() {
  Serial.begin(115200);
  uint32_t p1 = a * b / 100;                  // expected to overflow 32 bits number
  uint32_t p2 = a * b / 100.0;                // expected to calculate in float
  uint32_t p3 = float(a) * float(b) / 100.0;  // sure to calculate in float
  Serial.println("ImplicitConversion");
  Serial.print("p1 ");
  Serial.print(p1);
  Serial.print("  p2 ");
  Serial.print(p2);
  Serial.print("  p3 ");
  Serial.println(p3);
}

void loop() {}

  uint32_t p2 = a * b / 100.0;                // expected to calculate in float

The multiplication is being done using uint32_t, then the result converted to float for the division. Cast either a or b to float and you will get the expected answer.

Did you get any compiler warnings?

No warnings. And I have 'Compiler warnings: all' selected.

Exactly my point: adding a decimal point to the third number makes one expect the calculation will be done in float.
Wrong.
But: explicit conversion of one of the variables will indeed trigger implicit conversion of the other.

The expectation would be different if the equation were written like this:

(a * b) / 100.0

But there is no difference from the way you have written it, just an unnecessary set of parenthesis.

a * b / 100.0

It's just a feeling, but I feel like adding those parentheses decouples the third number, giving the compiler even more freedom in implementing the calculation of the first two.
Point remains: the phrase 'doing math with floats, you need to add a decimal point' gives a very much simplified view of things.

Compare

  uint32_t p2 = a / 100.0 * b;

The math is always using two operands at a time (except for like negation). So in this case, integer and double is performed as double; then double and integer. Nothing particularly tricky happening.

The Arduino Language Reference is of course aimed at a non-expert user group and can oversimplify some of the underlying C++ rules for brevity. For a more detailed treatment of the subject there is this: Implicit conversions - cppreference.com

This is contradictory to the old fashioned PEMDAS, but apparently calculations are done left-to-right. I'll have to get used to it.

As Google says

No it doesn't. calculations are done in order of priority and since the 2nd calculation does not have priority over the first, those to uint32_t variables are calculated using 32-bit integer. and then temporarily stored in one before the 2nd calculation takes place.
Since division and multiplication have equal priority, forcing a float calculation could be done either by casting or by moving the division to the left.

  uint32_t p2 = b / 100.0 * a; 

It is not something that you should be warned about.

C++ Operator Precedence

Lesson to be learned: Don't let the compiler decide for you!

uint32_t p2 = a * (b/100.0);
should work as expected, right?