Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -1167,6 +1167,14 @@ if (ParensAreType && !ParensCouldEndDecl) return true; + // Some more obscure casts can leak through the above heuristic, like + // (type* const)bar or (type* MACRO)bar + if (Tok.Next->is(tok::identifier) && Tok.Previous && + Tok.Previous->isOneOf(tok::kw_const, tok::identifier) && + Tok.Previous->Previous && + Tok.Previous->Previous->is(TT_PointerOrReference)) + return true; + // At this point, we heuristically assume that there are no casts at the // start of the line. We assume that we have found most cases where there // are by the logic above, e.g. "(void)x;". @@ -1260,6 +1268,17 @@ if (NextNextToken && NextNextToken->is(tok::arrow)) return TT_BinaryOperator; + // Casts are never binary operators, regardless of IsExpression + if (NextToken->isOneOf(tok::r_paren, tok::greater)) + return TT_PointerOrReference; + if (NextToken->isOneOf(tok::identifier, tok::kw_const) && NextNextToken && + NextNextToken->is(tok::r_paren) && NextNextToken->Next && + NextNextToken->Next->isOneOf(tok::identifier, tok::l_paren) && + (!PrevToken->Previous || !PrevToken->Previous->is(tok::l_paren) || + !PrevToken->Previous->Previous || + !PrevToken->Previous->Previous->is(tok::kw_decltype))) + return TT_PointerOrReference; + // It is very unlikely that we are going to find a pointer or reference type // definition on the RHS of an assignment. if (IsExpression && !Contexts.back().CaretFound) Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -5882,6 +5882,15 @@ "operator()() && {}"); verifyGoogleFormat("template \n" "auto x() & -> int {}"); + + // Some casts look like they might be multiplications, but they are definitely + // not! + // Here, foo could be a macro containing e.g. `const` + verifyFormat("(type *foo)bar"); + verifyFormat("(type *const)bar"); + verifyFormat("type *x = (type *foo)bar"); + verifyFormat("type *const x = (type *const)bar"); + verifyFormat("type *x = (type *foo)(bar)"); } TEST_F(FormatTest, UnderstandsAttributes) {