forked from OSchip/llvm-project
Improve clang-format's c-style cast detection.
Before: x[(uint8) y]; x = (uint8) y; void f() { x = (uint8) y; } #define AA(X) sizeof(((X *) NULL)->a) After: x[(uint8)y]; x = (uint8)y; void f() { x = (uint8)y; } #define AA(X) sizeof(((X *)NULL)->a) llvm-svn: 183014
This commit is contained in:
parent
4d14144024
commit
da6f225ef9
|
@ -602,19 +602,35 @@ private:
|
|||
else
|
||||
Current.Type = TT_BlockComment;
|
||||
} else if (Current.is(tok::r_paren)) {
|
||||
bool ParensNotExpr = !Current.Previous ||
|
||||
FormatToken *LeftOfParens = NULL;
|
||||
if (Current.MatchingParen)
|
||||
LeftOfParens = Current.MatchingParen->getPreviousNoneComment();
|
||||
bool IsCast = false;
|
||||
bool ParensAreEmpty = Current.Previous == Current.MatchingParen;
|
||||
bool ParensAreType = !Current.Previous ||
|
||||
Current.Previous->Type == TT_PointerOrReference ||
|
||||
Current.Previous->Type == TT_TemplateCloser;
|
||||
Current.Previous->Type == TT_TemplateCloser ||
|
||||
isSimpleTypeSpecifier(*Current.Previous);
|
||||
bool ParensCouldEndDecl =
|
||||
Current.Next &&
|
||||
Current.Next->isOneOf(tok::equal, tok::semi, tok::l_brace);
|
||||
bool IsSizeOfOrAlignOf =
|
||||
Current.MatchingParen && Current.MatchingParen->Previous &&
|
||||
Current.MatchingParen->Previous->isOneOf(tok::kw_sizeof,
|
||||
tok::kw_alignof);
|
||||
if (ParensNotExpr && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
|
||||
LeftOfParens &&
|
||||
LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
|
||||
if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
|
||||
Contexts.back().IsExpression)
|
||||
// FIXME: We need to get smarter and understand more cases of casts.
|
||||
IsCast = true;
|
||||
if (Current.Next &&
|
||||
(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->Type != TT_ObjCMethodExpr && Current.Next &&
|
||||
(Current.Next->is(tok::identifier)))
|
||||
IsCast = true;
|
||||
if (IsCast && !ParensAreEmpty)
|
||||
Current.Type = TT_CastRParen;
|
||||
} else if (Current.is(tok::at) && Current.Next) {
|
||||
switch (Current.Next->Tok.getObjCKeywordID()) {
|
||||
|
@ -677,7 +693,7 @@ private:
|
|||
|
||||
TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
|
||||
const FormatToken *PrevToken = Tok.getPreviousNoneComment();
|
||||
if (PrevToken == NULL)
|
||||
if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
|
||||
return TT_UnaryOperator;
|
||||
|
||||
// Use heuristics to recognize unary operators.
|
||||
|
@ -697,7 +713,7 @@ private:
|
|||
/// \brief Determine whether ++/-- are pre- or post-increments/-decrements.
|
||||
TokenType determineIncrementUsage(const FormatToken &Tok) {
|
||||
const FormatToken *PrevToken = Tok.getPreviousNoneComment();
|
||||
if (PrevToken == NULL)
|
||||
if (PrevToken == NULL || PrevToken->Type == TT_CastRParen)
|
||||
return TT_UnaryOperator;
|
||||
if (PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::identifier))
|
||||
return TT_TrailingUnaryOperator;
|
||||
|
@ -780,11 +796,11 @@ public:
|
|||
int CurrentPrecedence = 0;
|
||||
if (Current) {
|
||||
if (Current->Type == TT_ConditionalExpr)
|
||||
CurrentPrecedence = 1 + (int) prec::Conditional;
|
||||
CurrentPrecedence = 1 + (int)prec::Conditional;
|
||||
else if (Current->is(tok::semi) || Current->Type == TT_InlineASMColon)
|
||||
CurrentPrecedence = 1;
|
||||
else if (Current->Type == TT_BinaryOperator || Current->is(tok::comma))
|
||||
CurrentPrecedence = 1 + (int) Current->getPrecedence();
|
||||
CurrentPrecedence = 1 + (int)Current->getPrecedence();
|
||||
}
|
||||
|
||||
// At the end of the line or when an operator with higher precedence is
|
||||
|
|
|
@ -3173,10 +3173,24 @@ TEST_F(FormatTest, FormatsCasts) {
|
|||
verifyFormat("Type *A = (Type *)P;");
|
||||
verifyFormat("Type *A = (vector<Type *, int *>)P;");
|
||||
verifyFormat("int a = (int)(2.0f);");
|
||||
verifyFormat("int a = (int)2.0f;");
|
||||
verifyFormat("x[(int32)y];");
|
||||
verifyFormat("x = (int32)y;");
|
||||
verifyFormat("#define AA(X) sizeof(((X *)NULL)->a)");
|
||||
verifyFormat("int a = (int)*b;");
|
||||
verifyFormat("int a = (int)2.0f;");
|
||||
verifyFormat("int a = (int)~0;");
|
||||
verifyFormat("int a = (int)++a;");
|
||||
verifyFormat("int a = (int)sizeof(int);");
|
||||
verifyFormat("int a = (int)+2;");
|
||||
verifyFormat("my_int a = (my_int)2.0f;");
|
||||
verifyFormat("my_int a = (my_int)sizeof(int);");
|
||||
|
||||
// FIXME: These also need to be identified.
|
||||
verifyFormat("int a = (int) 2.0f;");
|
||||
verifyFormat("int a = (int) * b;");
|
||||
// FIXME: Without type knowledge, this can still fall apart miserably.
|
||||
verifyFormat("void f() { my_int a = (my_int) * b; }");
|
||||
verifyFormat("my_int a = (my_int) ~0;");
|
||||
verifyFormat("my_int a = (my_int)++ a;");
|
||||
verifyFormat("my_int a = (my_int) + 2;");
|
||||
|
||||
// These are not casts.
|
||||
verifyFormat("void f(int *) {}");
|
||||
|
|
Loading…
Reference in New Issue