Author: benhamilton Date: Thu Feb 8 08:07:25 2018 New Revision: 324618 URL: http://llvm.org/viewvc/llvm-project?rev=324618&view=rev Log: [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 Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp cfe/trunk/lib/Format/ContinuationIndenter.h cfe/trunk/unittests/Format/FormatTestObjC.cpp Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=324618&r1=324617&r2=324618&view=diff ============================================================================== --- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original) +++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Thu Feb 8 08:07:25 2018 @@ -1285,6 +1285,9 @@ void ContinuationIndenter::moveStatePast 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 @@ std::unique_ptr<BreakableToken> Continua // 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; Modified: cfe/trunk/lib/Format/ContinuationIndenter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.h?rev=324618&r1=324617&r2=324618&view=diff ============================================================================== --- cfe/trunk/lib/Format/ContinuationIndenter.h (original) +++ cfe/trunk/lib/Format/ContinuationIndenter.h Thu Feb 8 08:07:25 2018 @@ -208,7 +208,8 @@ struct ParenState { NoLineBreakInOperand(false), LastOperatorWrapped(true), ContainsLineBreak(false), ContainsUnwrappedBuilder(false), AlignColons(true), ObjCSelectorNameFound(false), - HasMultipleNestedBlocks(false), NestedBlockInlined(false) {} + HasMultipleNestedBlocks(false), NestedBlockInlined(false), + IsInsideObjCArrayLiteral(false) {} /// \brief The position to which a specific parenthesis level needs to be /// indented. @@ -318,6 +319,10 @@ struct ParenState { /// "function" in JavaScript) is not wrapped to a new line. bool NestedBlockInlined : 1; + /// \brief \c true if the current \c ParenState represents an Objective-C + /// array literal. + bool IsInsideObjCArrayLiteral : 1; + bool operator<(const ParenState &Other) const { if (Indent != Other.Indent) return Indent < Other.Indent; Modified: cfe/trunk/unittests/Format/FormatTestObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestObjC.cpp?rev=324618&r1=324617&r2=324618&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTestObjC.cpp (original) +++ cfe/trunk/unittests/Format/FormatTestObjC.cpp Thu Feb 8 08:07:25 2018 @@ -975,6 +975,12 @@ TEST_F(FormatTestObjC, ObjCArrayLiterals verifyFormat("[someFunction someLooooooooooooongParameter:@[\n" " NSBundle.mainBundle.infoDictionary[@\"a\"]\n" "]];"); + Style.ColumnLimit = 20; + // We can't break string literals inside NSArray literals + // (that raises -Wobjc-string-concatenation). + verifyFormat("NSArray *foo = @[\n" + " @\"aaaaaaaaaaaaaaaaaaaaaaaaaa\"\n" + "];\n"); } } // end namespace } // end namespace format _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits