The compilers do know what the precedence rules are, but they know that programmers don't routinely consult the ISO standard, so they emit those warnings to reduce the chance of error. Compilers are tools that are designed to help programmers avoid bugs. If they don't help programmers, they aren't doing their job.
It ain't no surprise if you see the crap that passes for software these days and the nosedive in quality, but that's a rant for some other time...
True + True = True, because "true" means "not zero" and "false" means "zero". In most all languages that permit int->bool casting, if(2) will evaluate to "true".
The warnings clang and FCC generate are a style warning because it's unclear on casual reading. Even readers who know the precedence rules will typically want to insert the parentheses manually. If the meaning were undefined, the compiler would give an error, not a warning.
More importantly, only if you don’t rely on short circuiting logic.
(Not a big hot hatch connoisseur though, I must admit - I just remember the Saxo in particular as having a reputation of hitting a bad spot on the tradeoff graph for flimsiness/power/good sense of average member of target demographic.)
The analogy is that when you set 1 to true and 0 to false, 1 becomes the identity for AND, and 0 becomes the identity for OR. Just as 1 is the identity for multiplication and 0 is the identity for addition.
X * 0 = 0 | X ^ F = F
X * 1 = X | X ^ T = X
X + 0 = X | X V F = X
X + 1 = ? | X V T = T <-- This one breaks the analogy
With this, you can turn any logical expression into something that looks and feels like normal algebra, with the only weird exception being that both operators distribute over each other:
A * (B + C) = A*B + A*C
A + (B * C) = (A + B) * (A + C)
My own mnemonic: SAXO. Shift, And, Xor, Or. (Like a real Saxo, it's fun to go a bit faster like this, but you do have to trust everybody involved, because any accident is probably going to end up badly for you.)
And now you know the bitwise precedence as well! And this ordering actually works out tidily for common operations: "x=a<<sa|b<<sb|c<<sb"; "x=p>>n&m"; "x=x&~ma|a<<sa"; and so on. You do need brackets sometimes, but fewer than you'd think, and it helps the unusual cases stand out.
(Main annoying thing: a lot of compilers, even popular ones such as clang and gcc, don't actually seem to know what the precedence rules actually are, and generate warnings asking you to clarify. Presumably the authors didn't realise that C has an ISO standard, that can be consulted to answer this question? Very surprising.)