clang-format: better detection for multiplication operator

Kapfhammer kapf at student.ethz.ch
Sun Mar 30 07:49:07 PDT 2014


This is a fix for: http://llvm.org/bugs/show_bug.cgi?id=16500

Before: cout << a *b;
After : cout << a * b;

I tried to be conservative to have as few false positives as possible.
The following lines are still formatted wrong:

template <int i = a *b>
f(a *b);
a *b + c;

There's also the possibility to be more aggressive, but then the
following existing testcase would have been broken:

template <class CallbackClass>
using MyCallback = void (CallbackClass::*)(SomeObject *Data);

--

>From 2717f48825ecb1a24f6fe47400bbd3039d915120 Mon Sep 17 00:00:00 2001
From: Kapfhammer <kapf at student.ethz.ch>
Date: Sun, 30 Mar 2014 12:04:17 +0200
Subject: [PATCH] clang-format: Use binary operators as an indicator of for an expression and
 extend the test suite.

This solves the issue where the star was too often interpreted as a
pointer, e.g "cout<<a*b;" was formatted to "cout << a *b;" instead of
"cout << a * b;".  By marking statements more often an expression, the
function determineStarAmpUsage() is more reliable.

The test suite was extended.
---
 lib/Format/TokenAnnotator.cpp   | 11 +++++++++++
 unittests/Format/FormatTest.cpp | 15 +++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 6a0e034..2e1faec 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -798,6 +798,17 @@ private:
         // function declaration have been found.
         Current.Type = TT_TrailingAnnotation;
       }
+      
+      // A binary operator is most likely part of an expression
+      if (Current.Type == TT_BinaryOperator &&
+          !Current.isOneOf(tok::ampamp, tok::less, tok::greater,
+                           tok::greatergreater) &&
+          (!Current.Previous ||
+           Current.Previous->isNot(tok::kw_operator)) &&
+          Contexts.back().CanBeExpression &&
+          !Line.First->isOneOf(tok::kw_template, tok::kw_using)) {
+        Contexts.back().IsExpression = true;
+      }
     }
   }
 
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 7332fd0..a4eec3a 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -4610,6 +4610,21 @@ TEST_F(FormatTest, UnderstandsRvalueReferences) {
   verifyGoogleFormat("#define WHILE(a, b, c) while (a && (b == c))");
 }
 
+TEST_F(FormatTest, FormatsMultiplicationOperator) {
+  verifyFormat("operator*(type *a)");
+  verifyFormat("operator<<(type *a)");
+  verifyFormat("cout << (a * b)");
+  verifyFormat("cout << a * b");
+  verifyFormat("x + a * b");
+  verifyFormat("type (*f)(type *a)");
+  verifyFormat("type (&f)(type *a)");
+  verifyFormat("void f(type *a)");
+  verifyFormat("using f = void (*)(a *b)");
+  verifyFormat("template <typename T = void (*)(a *b)");
+  verifyFormat("using f = void (c::*)(a *b)");
+  verifyFormat("template <typename T = void (c::*)(a *b)>");
+}
+
 TEST_F(FormatTest, FormatsBinaryOperatorsPrecedingEquals) {
   verifyFormat("void f() {\n"
                "  x[aaaaaaaaa -\n"
-- 
1.9.1



More information about the cfe-commits mailing list