[clang-format] Do not break Objective-C string literals inside array literals

Summary:
Concatenating Objective-C string literals inside an array literal
raises the warning -Wobjc-string-concatenation (which is enabled by default).

clang-format currently splits and concatenates string literals like
the following:

  NSArray *myArray = @[ @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ];

into:

  NSArray *myArray =
        @[ @"aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
           @"aaaaaaaaa" ];

which raises the warning. This is https://bugs.llvm.org/show_bug.cgi?id=36153 .

The options I can think of to fix this are:

1) Have clang-format disable Wobjc-string-concatenation by emitting
pragmas around the formatted code
2) Have clang-format wrap the string literals in a macro (which
disables the warning)
3) Disable string splitting for Objective-C string literals inside
array literals

I think 1) has no precedent, and I couldn't find a good
identity() macro for 2). So, this diff implements 3).

Test Plan: make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests

Reviewers: jolesiak, stephanemoore, djasper

Reviewed By: jolesiak

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D42704

llvm-svn: 324618
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 6ee2995..14f8f05 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1285,6 +1285,9 @@
   State.Stack.back().NestedBlockIndent = NestedBlockIndent;
   State.Stack.back().BreakBeforeParameter = BreakBeforeParameter;
   State.Stack.back().HasMultipleNestedBlocks = Current.BlockParameterCount > 1;
+  State.Stack.back().IsInsideObjCArrayLiteral =
+      Current.is(TT_ArrayInitializerLSquare) && Current.Previous &&
+      Current.Previous->is(tok::at);
 }
 
 void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {
@@ -1578,6 +1581,11 @@
     // likely want to terminate the string before any line breaking is done.
     if (Current.IsUnterminatedLiteral)
       return nullptr;
+    // Don't break string literals inside Objective-C array literals (doing so
+    // raises the warning -Wobjc-string-concatenation).
+    if (State.Stack.back().IsInsideObjCArrayLiteral) {
+      return nullptr;
+    }
 
     StringRef Text = Current.TokenText;
     StringRef Prefix;