Added some heuristics to identify c style casting

Before:
void f() { my_int a = (my_int) * b; }
void f() { return P ? (my_int) * P : (my_int)0; }

After:
void f() { my_int a = (my_int)*b; }
void f() { return P ? (my_int)*P : (my_int)0; }

Differential Revision: http://reviews.llvm.org/D3576

llvm-svn: 207964
This commit is contained in:
Dinesh Dwivedi 2014-05-05 13:14:35 +00:00
parent 6af073b636
commit 76f98f8047
2 changed files with 46 additions and 17 deletions

View File

@ -756,6 +756,7 @@ private:
else
Current.Type = TT_BlockComment;
} else if (Current.is(tok::r_paren)) {
// FIXME: Pull cast detection into its own function.
FormatToken *LeftOfParens = NULL;
if (Current.MatchingParen)
LeftOfParens = Current.MatchingParen->getPreviousNonComment();
@ -776,19 +777,42 @@ private:
Contexts[Contexts.size() - 2].IsExpression) ||
(Current.Next && Current.Next->isBinaryOperator())))
IsCast = true;
if (Current.Next && Current.Next->isNot(tok::string_literal) &&
(Current.Next->Tok.isLiteral() ||
Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
else if (Current.Next && Current.Next->isNot(tok::string_literal) &&
(Current.Next->Tok.isLiteral() ||
Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
IsCast = true;
// If there is an identifier after the (), it is likely a cast, unless
// there is also an identifier before the ().
if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
LeftOfParens->is(tok::kw_return)) &&
LeftOfParens->Type != TT_OverloadedOperator &&
LeftOfParens->isNot(tok::at) &&
LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
Current.Next->is(tok::identifier))
IsCast = true;
else if (LeftOfParens &&
(LeftOfParens->Tok.getIdentifierInfo() == NULL ||
LeftOfParens->is(tok::kw_return)) &&
LeftOfParens->Type != TT_OverloadedOperator &&
LeftOfParens->isNot(tok::at) &&
LeftOfParens->Type != TT_TemplateCloser && Current.Next) {
if (Current.Next->isOneOf(tok::identifier, tok::numeric_constant)) {
IsCast = true;
} else {
// Use heuristics to recognize c style casting.
FormatToken *Prev = Current.Previous;
if (Prev && Prev->isOneOf(tok::amp, tok::star))
Prev = Prev->Previous;
if (Prev && Current.Next && Current.Next->Next) {
bool NextIsUnary = Current.Next->isUnaryOperator() ||
Current.Next->isOneOf(tok::amp, tok::star);
IsCast = NextIsUnary &&
Current.Next->Next->isOneOf(tok::identifier,
tok::numeric_constant);
}
for (; Prev != Current.MatchingParen; Prev = Prev->Previous) {
if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) {
IsCast = false;
break;
}
}
}
}
if (IsCast && !ParensAreEmpty)
Current.Type = TT_CastRParen;
} else if (Current.is(tok::at) && Current.Next) {

View File

@ -4741,12 +4741,18 @@ TEST_F(FormatTest, FormatsCasts) {
verifyFormat("#define x ((int)-1)");
verifyFormat("#define p(q) ((int *)&q)");
// FIXME: Without type knowledge, this can still fall apart miserably.
verifyFormat("void f() { my_int a = (my_int) * b; }");
verifyFormat("void f() { return P ? (my_int) * P : (my_int)0; }");
verifyFormat("my_int a = (my_int) ~0;");
verifyFormat("my_int a = (my_int)++ a;");
verifyFormat("my_int a = (my_int) + 2;");
verifyFormat("void f() { my_int a = (my_int)*b; }");
verifyFormat("void f() { return P ? (my_int)*P : (my_int)0; }");
verifyFormat("my_int a = (my_int)~0;");
verifyFormat("my_int a = (my_int)++a;");
verifyFormat("my_int a = (my_int)+2;");
verifyFormat("my_int a = (my_int)1;");
verifyFormat("my_int a = (my_int *)1;");
verifyFormat("my_int a = (const my_int)-1;");
verifyFormat("my_int a = (const my_int *)-1;");
// FIXME: single value wrapped with paren will be treated as cast.
verifyFormat("void f(int i = (kValue)*kMask) {}");
// Don't break after a cast's
verifyFormat("int aaaaaaaaaaaaaaaaaaaaaaaaaaa =\n"
@ -4767,7 +4773,6 @@ TEST_F(FormatTest, FormatsCasts) {
verifyFormat("void f(SmallVector<int>) {}");
verifyFormat("void f(SmallVector<int>);");
verifyFormat("void f(SmallVector<int>) = 0;");
verifyFormat("void f(int i = (kValue) * kMask) {}");
verifyFormat("void f(int i = (kA * kB) & kMask) {}");
verifyFormat("int a = sizeof(int) * b;");
verifyFormat("int a = alignof(int) * b;", getGoogleStyle());