benhamilton created this revision. benhamilton added reviewers: djasper, jolesiak. Herald added subscribers: cfe-commits, klimek.
The following C++ code was being detected by `guessLanguage()` as Objective-C: #define FOO(...) auto bar = [] __VA_ARGS__; This was because `[] __VA_ARGS__` is not currently detected as a C++ lambda expression (it has no parens or braces), so `TokenAnnotator::parseSquare()` incorrectly treats the opening square as an ObjC method expression. We have two options to fix this: 1. Parse `[] __VA_ARGS__` explicitly as a C++ lambda 2. Make it so `[]` is never parsed as an Objective-C method expression This diff implements option 2, which causes the `[` to be parsed as `TT_ArraySubscriptLSquare` instead of `TT_ObjCMethodExpr`. Note that when I fixed this, it caused one change in formatting behavior, where the following was implicitly relying on the `[` being parsed as `TT_ObjCMethodExpr`: A<int * []> a; becomes: A<int *[]> a; with `Style.PointerAlignment = Middle`. I don't really know what the desired format is for this syntax; the test was added by Janusz Sobczak and integrated by @djasper in https://github.com/llvm-mirror/clang/commit/b511fe9818829d7ece0cc0b2ce1fbe04a1f0739a . I went ahead and changed the test for now. Test Plan: New tests added. Ran tests with: % make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests Repository: rC Clang https://reviews.llvm.org/D45169 Files: lib/Format/TokenAnnotator.cpp unittests/Format/FormatTest.cpp Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -6035,14 +6035,15 @@ PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("delete *x;", PointerMiddle); verifyFormat("int * x;", PointerMiddle); + verifyFormat("int *[] x;", PointerMiddle); verifyFormat("template <int * y> f() {}", PointerMiddle); verifyFormat("int * f(int * a) {}", PointerMiddle); verifyFormat("int main(int argc, char ** argv) {}", PointerMiddle); verifyFormat("Test::Test(int b) : a(b * b) {}", PointerMiddle); verifyFormat("A<int *> a;", PointerMiddle); verifyFormat("A<int **> a;", PointerMiddle); verifyFormat("A<int *, int *> a;", PointerMiddle); - verifyFormat("A<int * []> a;", PointerMiddle); + verifyFormat("A<int *[]> a;", PointerMiddle); verifyFormat("A = new SomeType *[Length]();", PointerMiddle); verifyFormat("A = new SomeType *[Length];", PointerMiddle); verifyFormat("T ** t = new T *;", PointerMiddle); @@ -12106,6 +12107,9 @@ FormatStyle::LK_ObjC, guessLanguage("foo.h", "#define MY_POINT_MAKE(x, y) CGPointMake((x), (y));\n")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO(...) auto bar = [] __VA_ARGS__;")); } TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) { Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -386,7 +386,7 @@ bool StartsObjCMethodExpr = !CppArrayTemplates && Style.isCpp() && !IsCpp11AttributeSpecifier && Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) && - CurrentToken->isNot(tok::l_brace) && + !CurrentToken->isOneOf(tok::l_brace, tok::r_square) && (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, tok::kw_return, tok::kw_throw) ||
Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -6035,14 +6035,15 @@ PointerMiddle.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("delete *x;", PointerMiddle); verifyFormat("int * x;", PointerMiddle); + verifyFormat("int *[] x;", PointerMiddle); verifyFormat("template <int * y> f() {}", PointerMiddle); verifyFormat("int * f(int * a) {}", PointerMiddle); verifyFormat("int main(int argc, char ** argv) {}", PointerMiddle); verifyFormat("Test::Test(int b) : a(b * b) {}", PointerMiddle); verifyFormat("A<int *> a;", PointerMiddle); verifyFormat("A<int **> a;", PointerMiddle); verifyFormat("A<int *, int *> a;", PointerMiddle); - verifyFormat("A<int * []> a;", PointerMiddle); + verifyFormat("A<int *[]> a;", PointerMiddle); verifyFormat("A = new SomeType *[Length]();", PointerMiddle); verifyFormat("A = new SomeType *[Length];", PointerMiddle); verifyFormat("T ** t = new T *;", PointerMiddle); @@ -12106,6 +12107,9 @@ FormatStyle::LK_ObjC, guessLanguage("foo.h", "#define MY_POINT_MAKE(x, y) CGPointMake((x), (y));\n")); + EXPECT_EQ( + FormatStyle::LK_Cpp, + guessLanguage("foo.h", "#define FOO(...) auto bar = [] __VA_ARGS__;")); } TEST_F(FormatTest, GuessLanguageWithCpp11AttributeSpecifiers) { Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -386,7 +386,7 @@ bool StartsObjCMethodExpr = !CppArrayTemplates && Style.isCpp() && !IsCpp11AttributeSpecifier && Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) && - CurrentToken->isNot(tok::l_brace) && + !CurrentToken->isOneOf(tok::l_brace, tok::r_square) && (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, tok::kw_return, tok::kw_throw) ||
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits