forked from OSchip/llvm-project
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:
parent
6af073b636
commit
76f98f8047
|
|
@ -756,6 +756,7 @@ private:
|
||||||
else
|
else
|
||||||
Current.Type = TT_BlockComment;
|
Current.Type = TT_BlockComment;
|
||||||
} else if (Current.is(tok::r_paren)) {
|
} else if (Current.is(tok::r_paren)) {
|
||||||
|
// FIXME: Pull cast detection into its own function.
|
||||||
FormatToken *LeftOfParens = NULL;
|
FormatToken *LeftOfParens = NULL;
|
||||||
if (Current.MatchingParen)
|
if (Current.MatchingParen)
|
||||||
LeftOfParens = Current.MatchingParen->getPreviousNonComment();
|
LeftOfParens = Current.MatchingParen->getPreviousNonComment();
|
||||||
|
|
@ -776,19 +777,42 @@ private:
|
||||||
Contexts[Contexts.size() - 2].IsExpression) ||
|
Contexts[Contexts.size() - 2].IsExpression) ||
|
||||||
(Current.Next && Current.Next->isBinaryOperator())))
|
(Current.Next && Current.Next->isBinaryOperator())))
|
||||||
IsCast = true;
|
IsCast = true;
|
||||||
if (Current.Next && Current.Next->isNot(tok::string_literal) &&
|
else if (Current.Next && Current.Next->isNot(tok::string_literal) &&
|
||||||
(Current.Next->Tok.isLiteral() ||
|
(Current.Next->Tok.isLiteral() ||
|
||||||
Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
|
Current.Next->isOneOf(tok::kw_sizeof, tok::kw_alignof)))
|
||||||
IsCast = true;
|
IsCast = true;
|
||||||
// If there is an identifier after the (), it is likely a cast, unless
|
// If there is an identifier after the (), it is likely a cast, unless
|
||||||
// there is also an identifier before the ().
|
// there is also an identifier before the ().
|
||||||
if (LeftOfParens && (LeftOfParens->Tok.getIdentifierInfo() == NULL ||
|
else if (LeftOfParens &&
|
||||||
LeftOfParens->is(tok::kw_return)) &&
|
(LeftOfParens->Tok.getIdentifierInfo() == NULL ||
|
||||||
LeftOfParens->Type != TT_OverloadedOperator &&
|
LeftOfParens->is(tok::kw_return)) &&
|
||||||
LeftOfParens->isNot(tok::at) &&
|
LeftOfParens->Type != TT_OverloadedOperator &&
|
||||||
LeftOfParens->Type != TT_TemplateCloser && Current.Next &&
|
LeftOfParens->isNot(tok::at) &&
|
||||||
Current.Next->is(tok::identifier))
|
LeftOfParens->Type != TT_TemplateCloser && Current.Next) {
|
||||||
IsCast = true;
|
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)
|
if (IsCast && !ParensAreEmpty)
|
||||||
Current.Type = TT_CastRParen;
|
Current.Type = TT_CastRParen;
|
||||||
} else if (Current.is(tok::at) && Current.Next) {
|
} else if (Current.is(tok::at) && Current.Next) {
|
||||||
|
|
|
||||||
|
|
@ -4741,12 +4741,18 @@ TEST_F(FormatTest, FormatsCasts) {
|
||||||
verifyFormat("#define x ((int)-1)");
|
verifyFormat("#define x ((int)-1)");
|
||||||
verifyFormat("#define p(q) ((int *)&q)");
|
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() { my_int a = (my_int) * b; }");
|
verifyFormat("void f() { return P ? (my_int)*P : (my_int)0; }");
|
||||||
verifyFormat("void f() { return P ? (my_int) * P : (my_int)0; }");
|
verifyFormat("my_int a = (my_int)~0;");
|
||||||
verifyFormat("my_int a = (my_int) ~0;");
|
verifyFormat("my_int a = (my_int)++a;");
|
||||||
verifyFormat("my_int a = (my_int)++ a;");
|
verifyFormat("my_int a = (my_int)+2;");
|
||||||
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
|
// Don't break after a cast's
|
||||||
verifyFormat("int aaaaaaaaaaaaaaaaaaaaaaaaaaa =\n"
|
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>);");
|
verifyFormat("void f(SmallVector<int>);");
|
||||||
verifyFormat("void f(SmallVector<int>) = 0;");
|
verifyFormat("void f(SmallVector<int>) = 0;");
|
||||||
verifyFormat("void f(int i = (kValue) * kMask) {}");
|
|
||||||
verifyFormat("void f(int i = (kA * kB) & kMask) {}");
|
verifyFormat("void f(int i = (kA * kB) & kMask) {}");
|
||||||
verifyFormat("int a = sizeof(int) * b;");
|
verifyFormat("int a = sizeof(int) * b;");
|
||||||
verifyFormat("int a = alignof(int) * b;", getGoogleStyle());
|
verifyFormat("int a = alignof(int) * b;", getGoogleStyle());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue