r207964 - Added some heuristics to identify c style casting

Dinesh Dwivedi dinesh.d at samsung.com
Mon May 5 06:14:35 PDT 2014


Author: dinesh
Date: Mon May  5 08:14:35 2014
New Revision: 207964

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


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=207964&r1=207963&r2=207964&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Mon May  5 08:14:35 2014
@@ -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) {

Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=207964&r1=207963&r2=207964&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Mon May  5 08:14:35 2014
@@ -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());





More information about the cfe-commits mailing list