Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -998,8 +998,14 @@ Current.Type = TT_LineComment; } } else if (Current.is(tok::r_paren)) { - if (rParenEndsCast(Current)) + if (rParenEndsCast(Current)) { Current.Type = TT_CastRParen; + for (FormatToken *tok = Current.MatchingParen; tok && tok != &Current; + tok = tok->Next) + // `*` in casts are never binary operators + if (tok->is(tok::star) && tok->is(TT_BinaryOperator)) + tok->Type = TT_PointerOrReference; + } if (Current.MatchingParen && Current.Next && !Current.Next->isBinaryOperator() && !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace, @@ -1167,6 +1173,13 @@ 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->isOneOf(tok::identifier, tok::l_paren) && Tok.Previous && + Tok.Previous->isOneOf(tok::kw_const, tok::identifier) && + Tok.Previous->Previous && Tok.Previous->Previous->is(tok::star)) + 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;". Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -5882,6 +5882,24 @@ "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 *restrict)bar"); + verifyFormat("(type *foo)(bar)"); + verifyFormat("(type *const)(bar)"); + verifyFormat("(type *restrict)(bar)"); + verifyFormat("type *x = (type *foo)bar"); + verifyFormat("type *const x = (type *const)bar"); + verifyFormat("type *x = (type *foo)(bar)"); + + FormatStyle LeftPointer = getLLVMStyle(); + LeftPointer.PointerAlignment = FormatStyle::PAS_Left; + verifyFormat("int x = a[(sint16*)pIn - j]", LeftPointer); + verifyFormat("int x = a[(int*)pIn - j]", LeftPointer); } TEST_F(FormatTest, UnderstandsAttributes) {