Fix formatting of pointers to members.
Before: int(S::*func)(void *);
After: int (S::*func)(void *);
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181438 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index c736e90..ab9c8c8 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -173,6 +173,9 @@
}
if (CurrentToken->isOneOf(tok::r_square, tok::r_brace))
return false;
+ if (CurrentToken->Parent->Type == TT_PointerOrReference &&
+ CurrentToken->Parent->Parent->isOneOf(tok::l_paren, tok::coloncolon))
+ Left->DefinesFunctionType = true;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
return false;
@@ -1025,6 +1028,9 @@
return Left.FormatTok.Tok.isLiteral() ||
((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
!Style.PointerBindsToType);
+ if (Right.DefinesFunctionType &&
+ (Left.Type != TT_PointerOrReference || Style.PointerBindsToType))
+ return true;
if (Left.Type == TT_PointerOrReference)
return Right.FormatTok.Tok.isLiteral() ||
((Right.Type != TT_PointerOrReference) &&
@@ -1091,13 +1097,6 @@
if (Tok.is(tok::colon))
return !Line.First.isOneOf(tok::kw_case, tok::kw_default) &&
Tok.getNextNoneComment() != NULL && Tok.Type != TT_ObjCMethodExpr;
- if (Tok.is(tok::l_paren) && !Tok.Children.empty() &&
- Tok.Children[0].Type == TT_PointerOrReference &&
- !Tok.Children[0].Children.empty() &&
- Tok.Children[0].Children[0].isNot(tok::r_paren) &&
- Tok.Parent->isNot(tok::l_paren) &&
- (Tok.Parent->Type != TT_PointerOrReference || Style.PointerBindsToType))
- return true;
if (Tok.Parent->Type == TT_UnaryOperator || Tok.Parent->Type == TT_CastRParen)
return false;
if (Tok.Type == TT_UnaryOperator)
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index b364082..a2080b5 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -75,7 +75,7 @@
CanBreakBefore(false), MustBreakBefore(false),
ClosesTemplateDeclaration(false), MatchingParen(NULL),
ParameterCount(0), BindingStrength(0), SplitPenalty(0),
- LongestObjCSelectorName(0), Parent(NULL),
+ LongestObjCSelectorName(0), DefinesFunctionType(false), Parent(NULL),
FakeRParens(0), LastInChainOfCalls(false),
PartOfMultiVariableDeclStmt(false), NoMoreTokensOnLevel(false) {}
@@ -164,6 +164,9 @@
/// definition or call, this contains the length of the longest name.
unsigned LongestObjCSelectorName;
+ /// \brief \c true if this is a "(" that starts a function type definition.
+ bool DefinesFunctionType;
+
std::vector<AnnotatedToken> Children;
AnnotatedToken *Parent;
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 3a97abe..715c55f 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -2417,14 +2417,15 @@
TEST_F(FormatTest, UnderstandsPointersToMembers) {
verifyFormat("int A::*x;");
- // FIXME: Recognize pointers to member functions.
- //verifyFormat("int (S::*func)(void *);");
- verifyFormat("int(S::*func)(void *);");
- verifyFormat("(a->*f)();");
- verifyFormat("a->*x;");
- verifyFormat("(a.*f)();");
- verifyFormat("((*a).*f)();");
- verifyFormat("a.*x;");
+ verifyFormat("int (S::*func)(void *);");
+ verifyFormat("typedef bool (Class::*Member)() const;");
+ verifyFormat("void f() {\n"
+ " (a->*f)();\n"
+ " a->*x;\n"
+ " (a.*f)();\n"
+ " ((*a).*f)();\n"
+ " a.*x;\n"
+ "}");
}
TEST_F(FormatTest, UnderstandsUnaryOperators) {