r183014 - Improve clang-format's c-style cast detection.

Daniel Jasper djasper at google.com
Fri May 31 09:14:28 PDT 2013


Author: djasper
Date: Fri May 31 11:14:28 2013
New Revision: 183014

URL: http://llvm.org/viewvc/llvm-project?rev=183014&view=rev
Log:
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)

Modified:
    cfe/trunk/lib/Format/TokenAnnotator.cpp
    cfe/trunk/unittests/Format/FormatTest.cpp

Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=183014&r1=183013&r2=183014&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Fri May 31 11:14:28 2013
@@ -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

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=183014&r1=183013&r2=183014&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Fri May 31 11:14:28 2013
@@ -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 *) {}");





More information about the cfe-commits mailing list