]> granicus.if.org Git - clang/commitdiff
Added some heuristics to identify c style casting
authorDinesh Dwivedi <dinesh.d@samsung.com>
Mon, 5 May 2014 13:14:35 +0000 (13:14 +0000)
committerDinesh Dwivedi <dinesh.d@samsung.com>
Mon, 5 May 2014 13:14:35 +0000 (13:14 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207964 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 65c0cabffc110a95c5babe2bf7380914b3ee7857..a6e04c54a21942c4368eebdbe2b974cc710e59da 100644 (file)
@@ -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) {
index 7db87cb3ce54f510a18caaf7273e4b7809f87ed1..d1f4c86bda861aba9dae0994f639c8424a4426c7 100644 (file)
@@ -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());