benhamilton updated this revision to Diff 137015.
benhamilton marked 7 inline comments as done.
benhamilton added a comment.
Fixes from @jolesiak
Repository:
rC Clang
https://reviews.llvm.org/D43902
Files:
lib/Format/FormatToken.h
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTest.cpp
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -12080,6 +12080,36 @@
EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo", "@interface Foo\n@end\n"));
}
+TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) {
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[noreturn]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "array[[calculator getIndex]];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"so sorry\")]];"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"gone, sorry\")]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[noreturn foo] bar];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[clang::fallthrough]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[clang:fallthrough] foo];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[gsl::suppress(\"type\")]];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[using clang: fallthrough]];"));
+ EXPECT_EQ(FormatStyle::LK_ObjC,
+ guessLanguage("foo.h", "[[abusing clang:fallthrough] bar];"));
+ EXPECT_EQ(FormatStyle::LK_Cpp,
+ guessLanguage("foo.h", "[[using gsl: suppress(\"type\")]];"));
+ EXPECT_EQ(
+ FormatStyle::LK_Cpp,
+ guessLanguage("foo.h",
+ "[[clang::callable_when(\"unconsumed\", \"unknown\")]]"));
+ EXPECT_EQ(FormatStyle::LK_Cpp, guessLanguage("foo.h", "[[foo::bar, ...]]"));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
Index: lib/Format/TokenAnnotator.cpp
===================================================================
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -320,13 +320,68 @@
return false;
}
+ const FormatToken *parseCpp11Attribute(const FormatToken &Tok,
+ bool NamespaceAllowed) {
+ if (!Tok.isOneOf(tok::identifier, tok::ellipsis))
+ return nullptr;
+ const FormatToken *AttrTok = Tok.Next;
+ if (!AttrTok)
+ return nullptr;
+ if (NamespaceAllowed &&
+ AttrTok->startsSequence(tok::coloncolon, tok::identifier)) {
+ AttrTok = AttrTok->Next->Next;
+ }
+ if (!AttrTok)
+ return nullptr;
+ if (AttrTok->is(tok::l_paren)) {
+ const FormatToken *ParamToken = AttrTok->Next;
+ while (ParamToken && ParamToken->isNot(tok::r_paren))
+ ParamToken = ParamToken->Next;
+ if (!ParamToken)
+ return nullptr;
+ AttrTok = ParamToken->Next;
+ }
+ return AttrTok;
+ }
+
+ // Look for [[ ... ]] which is a valid C++11 attribute specifier but
+ // never a valid Objective-C or Objective-C++ method invocation.
+ bool parseCpp11AttributeSpecifier(const FormatToken &Tok) {
+ if (!Style.isCpp())
+ return false;
+ if (!Tok.startsSequence(tok::l_square, tok::l_square))
+ return false;
+ const FormatToken *AttrTok = Tok.Next->Next;
+ if (!AttrTok)
+ return false;
+ bool NamespaceAllowed;
+ // C++17 '[[using namespace: foo, bar(baz, blech)]]'
+ if (AttrTok->startsSequence(tok::kw_using, tok::identifier, tok::colon)) {
+ AttrTok = AttrTok->Next->Next->Next;
+ NamespaceAllowed = false;
+ } else {
+ // C++11 '[[namespace::foo, namespace::bar(baz, blech)]]'
+ NamespaceAllowed = true;
+ }
+ while (AttrTok) {
+ AttrTok = parseCpp11Attribute(*AttrTok, NamespaceAllowed);
+ if (!AttrTok || AttrTok->isNot(tok::comma))
+ break;
+ AttrTok = AttrTok->Next;
+ }
+ if (!AttrTok)
+ return false;
+ return AttrTok->startsSequence(tok::r_square, tok::r_square);
+ }
+
bool parseSquare() {
if (!CurrentToken)
return false;
// A '[' could be an index subscript (after an identifier or after
// ')' or ']'), it could be the start of an Objective-C method
- // expression, or it could the start of an Objective-C array literal.
+ // expression, it could the start of an Objective-C array literal,
+ // or it could be a C++ attribute specifier [[foo::bar]].
FormatToken *Left = CurrentToken->Previous;
Left->ParentBracket = Contexts.back().ContextKind;
FormatToken *Parent = Left->getPreviousNonComment();
@@ -339,6 +394,12 @@
(Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
Contexts.back().InTemplateArgument);
+ if (parseCpp11AttributeSpecifier(*Left)) {
+ CurrentToken->Type = TT_AttributeSpecifier;
+ next();
+ return true;
+ }
+
bool StartsObjCMethodExpr =
!CppArrayTemplates && Style.isCpp() &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
Index: lib/Format/FormatToken.h
===================================================================
--- lib/Format/FormatToken.h
+++ lib/Format/FormatToken.h
@@ -30,6 +30,7 @@
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
TYPE(AttributeParen) \
+ TYPE(AttributeSpecifier) \
TYPE(BinaryOperator) \
TYPE(BitFieldColon) \
TYPE(BlockComment) \
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits