[clang-format] Don't detect C++11 attribute specifiers as ObjC
Summary:
Previously, clang-format would detect C++11 and C++17 attribute
specifiers like the following as Objective-C method invocations:
[[noreturn]];
[[clang::fallthrough]];
[[noreturn, deprecated("so sorry")]];
[[using gsl: suppress("type")]];
To fix this, I ported part of the logic from
tools/clang/lib/Parse/ParseTentative.cpp into TokenAnnotator.cpp so we
can explicitly parse and identify C++11 attribute specifiers.
This allows the guessLanguage() and getStyle() APIs to correctly
guess files containing the C++11 attribute specifiers as C++,
not Objective-C.
Test Plan: New tests added. Ran tests with:
make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests
Reviewers: krasimir, jolesiak, djasper
Reviewed By: djasper
Subscribers: aaron.ballman, cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D43902
llvm-svn: 327284
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 75667d5..7e0904c 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -6067,6 +6067,16 @@
AfterType);
}
+TEST_F(FormatTest, UnderstandsSquareAttributes) {
+ verifyFormat("SomeType s [[unused]] (InitValue);");
+ verifyFormat("SomeType s [[gnu::unused]] (InitValue);");
+ verifyFormat("SomeType s [[using gnu: unused]] (InitValue);");
+ verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}");
+ verifyFormat("void f() [[deprecated(\"so sorry\")]];");
+ verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);");
+}
+
TEST_F(FormatTest, UnderstandsEllipsis) {
verifyFormat("int printf(const char *fmt, ...);");
verifyFormat("template <class... Ts> void Foo(Ts... ts) { Foo(ts...); }");
@@ -12088,29 +12098,34 @@
EXPECT_EQ(FormatStyle::LK_ObjC, guessLanguage("foo", "@interface Foo\n@end\n"));
}
-TEST_F(FormatTest, GuessLanguageWithForIn) {
+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", "for (Foo *x = 0; x != in; x++) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in bar) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz]) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz:blech]) {}"));
- EXPECT_EQ(
- FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz:blech, 1, 2, 3, 0]) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "for (Foo *x in [bar baz:^{[uh oh];}]) {}"));
- EXPECT_EQ(FormatStyle::LK_Cpp,
- guessLanguage("foo.h", "Foo *x; for (x = 0; x != in; x++) {}"));
- EXPECT_EQ(FormatStyle::LK_ObjC,
- guessLanguage("foo.h", "Foo *x; for (x in y) {}"));
+ guessLanguage("foo.h", "[[noreturn, deprecated(\"so sorry\")]];"));
EXPECT_EQ(
FormatStyle::LK_Cpp,
- guessLanguage(
- "foo.h",
- "for (const Foo<Bar>& baz = in.value(); !baz.at_end(); ++baz) {}"));
+ 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