summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Format/TokenAnnotator.cpp12
-rw-r--r--unittests/Format/FormatTest.cpp42
2 files changed, 53 insertions, 1 deletions
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 50e3d056b8..0c41723821 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -2900,9 +2900,19 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
return true;
}
- if (Left.is(TT_UnaryOperator))
+ if (Left.is(TT_UnaryOperator)) {
+ // The alternative operators for ~ and ! are "compl" and "not".
+ // If they are used instead, we do not want to combine them with
+ // the token to the right, unless that is a left paren.
+ if (!Right.is(tok::l_paren)) {
+ if (Left.is(tok::exclaim) && Left.TokenText == "not")
+ return true;
+ if (Left.is(tok::tilde) && Left.TokenText == "compl")
+ return true;
+ }
return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
Right.is(TT_BinaryOperator);
+ }
// If the next token is a binary operator or a selector name, we have
// incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index b770d0f26f..14ac6f9137 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -14609,6 +14609,48 @@ TEST_F(FormatTest, AmbersandInLamda) {
verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle);
}
+TEST_F(FormatTest, AlternativeOperators) {
+ // Test case for ensuring alternate operators are not
+ // combined with their right most neighbour.
+ verifyFormat("int a and b;");
+ verifyFormat("int a and_eq b;");
+ verifyFormat("int a bitand b;");
+ verifyFormat("int a bitor b;");
+ verifyFormat("int a compl b;");
+ verifyFormat("int a not b;");
+ verifyFormat("int a not_eq b;");
+ verifyFormat("int a or b;");
+ verifyFormat("int a xor b;");
+ verifyFormat("int a xor_eq b;");
+ verifyFormat("return this not_eq bitand other;");
+ verifyFormat("bool operator not_eq(const X bitand other)");
+
+ verifyFormat("int a and 5;");
+ verifyFormat("int a and_eq 5;");
+ verifyFormat("int a bitand 5;");
+ verifyFormat("int a bitor 5;");
+ verifyFormat("int a compl 5;");
+ verifyFormat("int a not 5;");
+ verifyFormat("int a not_eq 5;");
+ verifyFormat("int a or 5;");
+ verifyFormat("int a xor 5;");
+ verifyFormat("int a xor_eq 5;");
+
+ verifyFormat("int a compl(5);");
+ verifyFormat("int a not(5);");
+
+ /* FIXME handle alternate tokens
+ * https://en.cppreference.com/w/cpp/language/operator_alternative
+ // alternative tokens
+ verifyFormat("compl foo();"); // ~foo();
+ verifyFormat("foo() <%%>;"); // foo();
+ verifyFormat("void foo() <%%>;"); // void foo(){}
+ verifyFormat("int a <:1:>;"); // int a[1];[
+ verifyFormat("%:define ABC abc"); // #define ABC abc
+ verifyFormat("%:%:"); // ##
+ */
+}
+
} // end namespace
} // end namespace format
} // end namespace clang