[PATCH] Some heuristics to identify c style casting (PR18937)

Dinesh Dwivedi dinesh.d at samsung.com
Wed Apr 30 14:19:38 PDT 2014


Hi djasper, klimek,

I have added few heuristics to identify c style casting. Only side 
effect of this patch is that single identifier wrapped with parentheses
(identifier) are getting treated as cast.

http://reviews.llvm.org/D3576

Files:
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTest.cpp

Index: lib/Format/TokenAnnotator.cpp
===================================================================
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -775,19 +775,45 @@
               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 { // Some heuristics to identify c style casting
+            FormatToken *Prev = Current.Previous;
+            if (Prev && Prev->isOneOf(tok::amp, tok::star))
+              Prev = Prev->Previous;
+
+            // if there is some unary operator after () and then an identifier
+            // it is likely a cast
+            if (Prev && (Current.Next->isUnaryOperator() ||
+                         Current.Next->isOneOf(tok::amp, tok::star)) &&
+                Current.Next->Next &&
+                Current.Next->Next->isOneOf(tok::identifier,
+                                            tok::numeric_constant))
+              IsCast = true;
+
+            // only tokens allowed inside () is const and some identifier
+            // isSimpleTypeSpecifier case is already handled above
+            while (Prev != Current.MatchingParen) {
+              if (!Prev || !Prev->isOneOf(tok::kw_const, tok::identifier)) {
+                IsCast = false;
+                break;
+              }
+              Prev = Prev->Previous;
+            }
+          }
+        }
         if (IsCast && !ParensAreEmpty)
           Current.Type = TT_CastRParen;
       } else if (Current.is(tok::at) && Current.Next) {
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -4741,12 +4741,18 @@
   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 @@
   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());
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3576.8991.patch
Type: text/x-patch
Size: 4662 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140430/1d933286/attachment.bin>


More information about the cfe-commits mailing list