if (NextToken->isOneOf(tok::comma, tok::semi))
return TT_PointerOrReference;
+ // After right braces, star tokens are likely to be pointers to struct,
+ // union, or class.
+ // struct {} *ptr;
+ if (PrevToken->is(tok::r_brace) && Tok.is(tok::star))
+ return TT_PointerOrReference;
+
+ // For "} &&"
+ if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp)) {
+ const FormatToken *MatchingLBrace = PrevToken->MatchingParen;
+
+ // We check whether there is a TemplateCloser(">") to indicate it's a
+ // template or not. If it's not a template, "&&" is likely a reference
+ // operator.
+ // struct {} &&ref = {};
+ if (!MatchingLBrace)
+ return TT_PointerOrReference;
+ FormatToken *BeforeLBrace = MatchingLBrace->getPreviousNonComment();
+ if (!BeforeLBrace || BeforeLBrace->isNot(TT_TemplateCloser))
+ return TT_PointerOrReference;
+
+ // If it is a template, "&&" is a binary operator.
+ // enable_if<>{} && ...
+ return TT_BinaryOperator;
+ }
+
if (PrevToken->Tok.isLiteral() ||
PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
tok::kw_false, tok::r_brace)) {
"void F();",
getGoogleStyleWithColumns(68));
+ FormatStyle Style = getLLVMStyle();
+ Style.PointerAlignment = FormatStyle::PAS_Left;
+ verifyFormat("struct {\n"
+ "}* ptr;",
+ Style);
+ verifyFormat("union {\n"
+ "}* ptr;",
+ Style);
+ verifyFormat("class {\n"
+ "}* ptr;",
+ Style);
+ verifyFormat("struct {\n"
+ "}&& ptr = {};",
+ Style);
+ verifyFormat("union {\n"
+ "}&& ptr = {};",
+ Style);
+ verifyFormat("class {\n"
+ "}&& ptr = {};",
+ Style);
+
+ Style.PointerAlignment = FormatStyle::PAS_Middle;
+ verifyFormat("struct {\n"
+ "} * ptr;",
+ Style);
+ verifyFormat("union {\n"
+ "} * ptr;",
+ Style);
+ verifyFormat("class {\n"
+ "} * ptr;",
+ Style);
+ verifyFormat("struct {\n"
+ "} && ptr = {};",
+ Style);
+ verifyFormat("union {\n"
+ "} && ptr = {};",
+ Style);
+ verifyFormat("class {\n"
+ "} && ptr = {};",
+ Style);
+
+ Style.PointerAlignment = FormatStyle::PAS_Right;
+ verifyFormat("struct {\n"
+ "} *ptr;",
+ Style);
+ verifyFormat("union {\n"
+ "} *ptr;",
+ Style);
+ verifyFormat("class {\n"
+ "} *ptr;",
+ Style);
+ verifyFormat("struct {\n"
+ "} &&ptr = {};",
+ Style);
+ verifyFormat("union {\n"
+ "} &&ptr = {};",
+ Style);
+ verifyFormat("class {\n"
+ "} &&ptr = {};",
+ Style);
+
verifyIndependentOfContext("MACRO(int *i);");
verifyIndependentOfContext("MACRO(auto *a);");
verifyIndependentOfContext("MACRO(const A *a);");
Tokens = annotate("case &x:");
EXPECT_EQ(Tokens.size(), 5u) << Tokens;
EXPECT_TOKEN(Tokens[1], tok::amp, TT_UnaryOperator);
+
+ Tokens = annotate("struct {\n"
+ "} *ptr;");
+ EXPECT_EQ(Tokens.size(), 7u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);
+ Tokens = annotate("union {\n"
+ "} *ptr;");
+ EXPECT_EQ(Tokens.size(), 7u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);
+ Tokens = annotate("class {\n"
+ "} *ptr;");
+ EXPECT_EQ(Tokens.size(), 7u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);
+
+ Tokens = annotate("struct {\n"
+ "} &&ptr = {};");
+ EXPECT_EQ(Tokens.size(), 10u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference);
+ Tokens = annotate("union {\n"
+ "} &&ptr = {};");
+ EXPECT_EQ(Tokens.size(), 10u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference);
+ Tokens = annotate("class {\n"
+ "} &&ptr = {};");
+ EXPECT_EQ(Tokens.size(), 10u) << Tokens;
+ EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference);
}
TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {