Fix another regression for pointer types.
authorDaniel Jasper <djasper@google.com>
Wed, 23 Jan 2013 12:10:53 +0000 (12:10 +0000)
committerDaniel Jasper <djasper@google.com>
Wed, 23 Jan 2013 12:10:53 +0000 (12:10 +0000)
Before: if (int * a = &b) ...
After:  if (int *a = &b) ...

Also changed all the existing tests to test the expressions in question
both in a declaration and in an expression context.

llvm-svn: 173256

clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp

index 36bf53d..2d9bd2c 100644 (file)
@@ -1237,7 +1237,7 @@ public:
     if (Line.Type == LT_Invalid)
       return;
 
-    determineTokenTypes(Line.First, /*IsRHS=*/false);
+    determineTokenTypes(Line.First, /*IsExpression=*/ false);
 
     if (Line.First.Type == TT_ObjCMethodSpecifier)
       Line.Type = LT_ObjCMethodDecl;
@@ -1256,16 +1256,23 @@ public:
   }
 
 private:
-  void determineTokenTypes(AnnotatedToken &Current, bool IsRHS) {
-    if (getPrecedence(Current) == prec::Assignment ||
-        Current.is(tok::kw_return) || Current.is(tok::kw_throw))
-      IsRHS = true;
-    if (Current.is(tok::l_paren) && !Line.MustBeDeclaration)
-      IsRHS = true;
+  void determineTokenTypes(AnnotatedToken &Current, bool IsExpression) {
+    if (getPrecedence(Current) == prec::Assignment) {
+      IsExpression = true;
+      AnnotatedToken *Previous = Current.Parent;
+      while (Previous != NULL) {
+        if (Previous->Type == TT_BinaryOperator)
+          Previous->Type = TT_PointerOrReference;
+        Previous = Previous->Parent;
+      }
+    }
+    if (Current.is(tok::kw_return) || Current.is(tok::kw_throw) ||
+        (Current.is(tok::l_paren) && !Line.MustBeDeclaration))
+      IsExpression = true;
 
     if (Current.Type == TT_Unknown) {
       if (Current.is(tok::star) || Current.is(tok::amp)) {
-        Current.Type = determineStarAmpUsage(Current, IsRHS);
+        Current.Type = determineStarAmpUsage(Current, IsExpression);
       } else if (Current.is(tok::minus) || Current.is(tok::plus) ||
                  Current.is(tok::caret)) {
         Current.Type = determinePlusMinusCaretUsage(Current);
@@ -1308,7 +1315,7 @@ private:
     }
 
     if (!Current.Children.empty())
-      determineTokenTypes(Current.Children[0], IsRHS);
+      determineTokenTypes(Current.Children[0], IsExpression);
   }
 
   bool isBinaryOperator(const AnnotatedToken &Tok) {
@@ -1338,7 +1345,8 @@ private:
   }
 
   /// \brief Return the type of the given token assuming it is * or &.
-  TokenType determineStarAmpUsage(const AnnotatedToken &Tok, bool IsRHS) {
+  TokenType determineStarAmpUsage(const AnnotatedToken &Tok,
+                                  bool IsExpression) {
     const AnnotatedToken *PrevToken = getPreviousToken(Tok);
     if (PrevToken == NULL)
       return TT_UnaryOperator;
@@ -1372,7 +1380,7 @@ private:
 
     // It is very unlikely that we are going to find a pointer or reference type
     // definition on the RHS of an assignment.
-    if (IsRHS)
+    if (IsExpression)
       return TT_BinaryOperator;
 
     return TT_PointerOrReference;
index 44f91c7..3a1cfb2 100644 (file)
@@ -100,6 +100,11 @@ protected:
   void verifyGoogleFormat(llvm::StringRef Code) {
     verifyFormat(Code, getGoogleStyle());
   }
+
+  void verifyIndependentOfContext(llvm::StringRef text) {
+    verifyFormat(text);
+    verifyFormat(llvm::Twine("void f() { " + text + " }").str());
+  }
 };
 
 TEST_F(FormatTest, MessUp) {
@@ -1276,45 +1281,44 @@ TEST_F(FormatTest, UnderstandsNewAndDelete) {
 
 TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
   verifyFormat("int *f(int *a) {}");
-  verifyFormat("f(a, *a);");
-  verifyFormat("f(*a);");
-  verifyFormat("int a = b * 10;");
-  verifyFormat("int a = 10 * b;");
-  verifyFormat("int a = b * c;");
-  verifyFormat("int a += b * c;");
-  verifyFormat("int a -= b * c;");
-  verifyFormat("int a *= b * c;");
-  verifyFormat("int a /= b * c;");
-  verifyFormat("int a = *b;");
-  verifyFormat("int a = *b * c;");
-  verifyFormat("int a = b * *c;");
-  verifyFormat("void f() { int *a = b * c; }");
   verifyFormat("int main(int argc, char **argv) {}");
-  verifyFormat("return 10 * b;");
-  verifyFormat("return *b * *c;");
-  verifyFormat("return a & ~b;");
-  verifyFormat("f(b ? *c : *d);");
-  verifyFormat("int a = b ? *c : *d;");
-  verifyFormat("*b = a;");
-  verifyFormat("a * ~b;");
-  verifyFormat("a * !b;");
-  verifyFormat("a * +b;");
-  verifyFormat("a * -b;");
-  verifyFormat("a * ++b;");
-  verifyFormat("a * --b;");
-  verifyFormat("a[4] * b;");
-  verifyFormat("f() * b;");
-  verifyFormat("a * [self dostuff];");
-  verifyFormat("a * (a + b);");
-  verifyFormat("(a *)(a + b);");
-  verifyFormat("int *pa = (int *)&a;");
-
-  verifyFormat("InvalidRegions[*R] = 0;");
-
-  verifyFormat("A<int *> a;");
-  verifyFormat("A<int **> a;");
-  verifyFormat("A<int *, int *> a;");
-  verifyFormat("A<int **, int **> a;");
+  verifyIndependentOfContext("f(a, *a);");
+  verifyIndependentOfContext("f(*a);");
+  verifyIndependentOfContext("int a = b * 10;");
+  verifyIndependentOfContext("int a = 10 * b;");
+  verifyIndependentOfContext("int a = b * c;");
+  verifyIndependentOfContext("int a += b * c;");
+  verifyIndependentOfContext("int a -= b * c;");
+  verifyIndependentOfContext("int a *= b * c;");
+  verifyIndependentOfContext("int a /= b * c;");
+  verifyIndependentOfContext("int a = *b;");
+  verifyIndependentOfContext("int a = *b * c;");
+  verifyIndependentOfContext("int a = b * *c;");
+  verifyIndependentOfContext("return 10 * b;");
+  verifyIndependentOfContext("return *b * *c;");
+  verifyIndependentOfContext("return a & ~b;");
+  verifyIndependentOfContext("f(b ? *c : *d);");
+  verifyIndependentOfContext("int a = b ? *c : *d;");
+  verifyIndependentOfContext("*b = a;");
+  verifyIndependentOfContext("a * ~b;");
+  verifyIndependentOfContext("a * !b;");
+  verifyIndependentOfContext("a * +b;");
+  verifyIndependentOfContext("a * -b;");
+  verifyIndependentOfContext("a * ++b;");
+  verifyIndependentOfContext("a * --b;");
+  verifyIndependentOfContext("a[4] * b;");
+  verifyIndependentOfContext("f() * b;");
+  verifyIndependentOfContext("a * [self dostuff];");
+  verifyIndependentOfContext("a * (a + b);");
+  verifyIndependentOfContext("(a *)(a + b);");
+  verifyIndependentOfContext("int *pa = (int *)&a;");
+
+  verifyIndependentOfContext("InvalidRegions[*R] = 0;");
+
+  verifyIndependentOfContext("A<int *> a;");
+  verifyIndependentOfContext("A<int **> a;");
+  verifyIndependentOfContext("A<int *, int *> a;");
+  verifyIndependentOfContext("A<int **, int **> a;");
 
   verifyFormat(
       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
@@ -1333,28 +1337,28 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
   verifyGoogleFormat("Type* t = const_cast<T*>(&*x);");
   verifyGoogleFormat("Type* t = x++ * y;");
 
-  verifyFormat("a = *(x + y);");
-  verifyFormat("a = &(x + y);");
-  verifyFormat("*(x + y).call();");
-  verifyFormat("&(x + y)->call();");
-  verifyFormat("&(*I).first");
+  verifyIndependentOfContext("a = *(x + y);");
+  verifyIndependentOfContext("a = &(x + y);");
+  verifyIndependentOfContext("*(x + y).call();");
+  verifyIndependentOfContext("&(x + y)->call();");
+  verifyIndependentOfContext("&(*I).first");
 
-  verifyFormat("f(b * /* confusing comment */ ++c);");
+  verifyIndependentOfContext("f(b * /* confusing comment */ ++c);");
   verifyFormat(
       "int *MyValues = {\n"
       "  *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)");
+  verifyIndependentOfContext("if (int *a = &b)");
+  verifyIndependentOfContext("if (int &a = *b)");
+  verifyIndependentOfContext("if (a & b[i])");
+  verifyIndependentOfContext("if (a::b::c::d & b[i])");
+  verifyIndependentOfContext("if (*b[i])");
+  verifyIndependentOfContext("if (int *a = (&b))");
+  verifyIndependentOfContext("while (int *a = &b)");
 
-  verifyFormat("A = new SomeType *[Length]();");
+  verifyIndependentOfContext("A = new SomeType *[Length]();");
   verifyGoogleFormat("A = new SomeType* [Length]();");
 }