Formatter: Get bit tests in ifs right.

It's generally not possible to know if 'a' '*' 'b' is a multiplication
expression or a variable declaration with a purely lexer-based approach. The
formatter currently uses a heuristic that classifies this token sequence as a
multiplication in rhs contexts (after '=' or 'return') and as a declaration
else.

Because of this, it gets bit tests in ifs, such as "if (a & b)" wrong. However,
declarations in ifs always have to be followed by '=', so this patch changes
the formatter to classify '&' as an operator if it's at the start of an if
statement.

Before:
  if (a& b)
  if (int* b = f())

Now:
  if (a & b)
  if (int* b = f())



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172731 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index f8e1850..d1c3a4f 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -771,13 +771,28 @@
       return false;
     }
 
-    bool parseParens() {
+    bool parseParens(bool LookForDecls = false) {
       if (CurrentToken == NULL)
         return false;
       AnnotatedToken *Left = CurrentToken->Parent;
       if (CurrentToken->is(tok::caret))
         Left->Type = TT_ObjCBlockLParen;
       while (CurrentToken != NULL) {
+        // LookForDecls is set when "if (" has been seen. Check for
+        // 'identifier' '*' 'identifier' followed by not '=' -- this
+        // '*' has to be a binary operator but determineStarAmpUsage() will
+        // categorize it as an unary operator, so set the right type here.
+        if (LookForDecls && !CurrentToken->Children.empty()) {
+          AnnotatedToken &Prev = *CurrentToken->Parent;
+          AnnotatedToken &Next = CurrentToken->Children[0];
+          if (Prev.Parent->is(tok::identifier) &&
+              (Prev.is(tok::star) || Prev.is(tok::amp)) &&
+              CurrentToken->is(tok::identifier) && Next.isNot(tok::equal)) {
+            Prev.Type = TT_BinaryOperator;
+            LookForDecls = false;
+          }
+        }
+
         if (CurrentToken->is(tok::r_paren)) {
           Left->MatchingParen = CurrentToken;
           CurrentToken->MatchingParen = Left;
@@ -896,6 +911,14 @@
         if (ColonIsObjCMethodExpr)
           Tok->Type = TT_ObjCMethodExpr;
         break;
+      case tok::kw_if:
+      case tok::kw_while:
+        if (CurrentToken->is(tok::l_paren)) {
+          next();
+          if (!parseParens(/*LookForDecls=*/true))
+            return false;
+        }
+        break;
       case tok::l_paren: {
         if (!parseParens())
           return false;
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 28d9fbe..7b57e85 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -1235,6 +1235,14 @@
       "  *A, // Operator detection might be confused by the '{'\n"
       "  *BB // Operator detection might be confused by previous comment\n"
       "};");
+
+  verifyFormat("if (int *a = &b)");
+  verifyFormat("if (int &a = *b)");
+  verifyFormat("if (a & b[i])");
+  verifyFormat("if (a::b::c::d & b[i])");
+  verifyFormat("if (*b[i])");
+  verifyFormat("if (int *a = (&b))");
+  verifyFormat("while (int *a = &b)");
 }
 
 TEST_F(FormatTest, FormatsCasts) {