From b8b4295b4ee161bfb76ff7b0ec1007bfd959553b Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Fri, 31 May 2013 16:14:28 +0000 Subject: [PATCH] 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) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183014 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 38 +++++++++++++++++++++++---------- unittests/Format/FormatTest.cpp | 22 +++++++++++++++---- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 3e89f79444..5b228f8ace 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -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 diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 9e9a5f30d5..0b35abeb9b 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -3173,10 +3173,24 @@ TEST_F(FormatTest, FormatsCasts) { verifyFormat("Type *A = (Type *)P;"); verifyFormat("Type *A = (vector)P;"); verifyFormat("int a = (int)(2.0f);"); - - // FIXME: These also need to be identified. - verifyFormat("int a = (int) 2.0f;"); - verifyFormat("int a = (int) * b;"); + 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: 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 *) {}"); -- 2.40.0