Thank you and sorry for missing that. I actually knew that and correspondingly did not use an init list in Format.cpp, but forget to cleanup the test. Sorry for the inconvenience!
On Tue, Apr 1, 2014 at 6:37 PM, Aaron Ballman <[email protected]>wrote: > On Tue, Apr 1, 2014 at 8:55 AM, Daniel Jasper <[email protected]> wrote: > > Author: djasper > > Date: Tue Apr 1 07:55:11 2014 > > New Revision: 205307 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=205307&view=rev > > Log: > > clang-format: Support configurable list of foreach-macros. > > > > This fixes llvm.org/PR17242. > > > > Patch by Brian Green, thank you! > > > > Modified: > > cfe/trunk/docs/ClangFormatStyleOptions.rst > > cfe/trunk/include/clang/Format/Format.h > > cfe/trunk/lib/Format/Format.cpp > > cfe/trunk/lib/Format/FormatToken.h > > cfe/trunk/lib/Format/TokenAnnotator.cpp > > cfe/trunk/lib/Format/UnwrappedLineParser.cpp > > cfe/trunk/unittests/Format/FormatTest.cpp > > > > Modified: cfe/trunk/docs/ClangFormatStyleOptions.rst > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ClangFormatStyleOptions.rst?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/docs/ClangFormatStyleOptions.rst (original) > > +++ cfe/trunk/docs/ClangFormatStyleOptions.rst Tue Apr 1 07:55:11 2014 > > @@ -212,6 +212,14 @@ the configuration (without a prefix: ``A > > NOTE: This is an experimental flag, that might go away or be renamed. > Do > > not use this in config files, etc. Use at your own risk. > > > > +**ForEachMacros** (``std::vector<std::string>``) > > + A list of macros that should be interpreted as foreach loops instead > of as > > + function calls. > > + > > + For example, ``ForEachMacros: [BOOST_FOREACH, Q_FOREACH]`` tells > > + clang-format to treat ``BOOST_FOREACH`` and ``Q_FOREACH`` as loop > control > > + statements. > > + > > **IndentCaseLabels** (``bool``) > > Indent case labels one level from the switch statement. > > > > > > Modified: cfe/trunk/include/clang/Format/Format.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/include/clang/Format/Format.h (original) > > +++ cfe/trunk/include/clang/Format/Format.h Tue Apr 1 07:55:11 2014 > > @@ -302,6 +302,18 @@ struct FormatStyle { > > /// which should not be split into lines or otherwise changed. > > std::string CommentPragmas; > > > > + /// \brief A vector of macros that should be interpreted as foreach > loops > > + /// instead of as function calls. > > + /// > > + /// These are expected to be macros of the form: > > + /// \code > > + /// FOREACH(<variable-declaration>, ...) > > + /// <loop-body> > > + /// \endcode > > + /// > > + /// For example: BOOST_FOREACH. > > + std::vector<std::string> ForEachMacros; > > + > > bool operator==(const FormatStyle &R) const { > > return AccessModifierOffset == R.AccessModifierOffset && > > ConstructorInitializerIndentWidth == > > @@ -358,7 +370,8 @@ struct FormatStyle { > > SpaceBeforeParens == R.SpaceBeforeParens && > > SpaceBeforeAssignmentOperators == > R.SpaceBeforeAssignmentOperators && > > ContinuationIndentWidth == R.ContinuationIndentWidth && > > - CommentPragmas == R.CommentPragmas; > > + CommentPragmas == R.CommentPragmas && > > + ForEachMacros == R.ForEachMacros; > > } > > }; > > > > > > Modified: cfe/trunk/lib/Format/Format.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Format/Format.cpp (original) > > +++ cfe/trunk/lib/Format/Format.cpp Tue Apr 1 07:55:11 2014 > > @@ -33,6 +33,8 @@ > > > > using clang::format::FormatStyle; > > > > +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string) > > + > > namespace llvm { > > namespace yaml { > > template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { > > @@ -200,6 +202,7 @@ template <> struct MappingTraits<FormatS > > Style.SpaceBeforeAssignmentOperators); > > IO.mapOptional("ContinuationIndentWidth", > Style.ContinuationIndentWidth); > > IO.mapOptional("CommentPragmas", Style.CommentPragmas); > > + IO.mapOptional("ForEachMacros", Style.ForEachMacros); > > > > // For backward compatibility. > > if (!IO.outputting()) { > > @@ -259,11 +262,16 @@ FormatStyle getLLVMStyle() { > > LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; > > LLVMStyle.BreakConstructorInitializersBeforeComma = false; > > LLVMStyle.ColumnLimit = 80; > > + LLVMStyle.CommentPragmas = "^ IWYU pragma:"; > > LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; > > LLVMStyle.ConstructorInitializerIndentWidth = 4; > > + LLVMStyle.ContinuationIndentWidth = 4; > > LLVMStyle.Cpp11BracedListStyle = true; > > LLVMStyle.DerivePointerBinding = false; > > LLVMStyle.ExperimentalAutoDetectBinPacking = false; > > + LLVMStyle.ForEachMacros.push_back("foreach"); > > + LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); > > + LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); > > LLVMStyle.IndentCaseLabels = false; > > LLVMStyle.IndentFunctionDeclarationAfterType = false; > > LLVMStyle.IndentWidth = 2; > > @@ -283,9 +291,7 @@ FormatStyle getLLVMStyle() { > > LLVMStyle.SpacesInCStyleCastParentheses = false; > > LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; > > LLVMStyle.SpaceBeforeAssignmentOperators = true; > > - LLVMStyle.ContinuationIndentWidth = 4; > > LLVMStyle.SpacesInAngles = false; > > - LLVMStyle.CommentPragmas = "^ IWYU pragma:"; > > > > LLVMStyle.PenaltyBreakComment = 300; > > LLVMStyle.PenaltyBreakFirstLessLess = 120; > > @@ -1131,6 +1137,10 @@ public: > > TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr), > Style(Style), > > IdentTable(getFormattingLangOpts()), Encoding(Encoding) { > > Lex.SetKeepWhitespaceMode(true); > > + > > + for (const std::string& ForEachMacro : Style.ForEachMacros) > > + ForEachMacros.push_back(&IdentTable.get(ForEachMacro)); > > + std::sort(ForEachMacros.begin(), ForEachMacros.end()); > > } > > > > ArrayRef<FormatToken *> lex() { > > @@ -1351,6 +1361,10 @@ private: > > Column = FormatTok->LastLineColumnWidth; > > } > > > > + FormatTok->IsForEachMacro = > > + std::binary_search(ForEachMacros.begin(), ForEachMacros.end(), > > + FormatTok->Tok.getIdentifierInfo()); > > + > > return FormatTok; > > } > > > > @@ -1366,6 +1380,7 @@ private: > > encoding::Encoding Encoding; > > llvm::SpecificBumpPtrAllocator<FormatToken> Allocator; > > SmallVector<FormatToken *, 16> Tokens; > > + SmallVector<IdentifierInfo*, 8> ForEachMacros; > > > > void readRawToken(FormatToken &Tok) { > > Lex.LexFromRawLexer(Tok.Tok); > > > > Modified: cfe/trunk/lib/Format/FormatToken.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Format/FormatToken.h (original) > > +++ cfe/trunk/lib/Format/FormatToken.h Tue Apr 1 07:55:11 2014 > > @@ -104,7 +104,7 @@ struct FormatToken { > > SplitPenalty(0), LongestObjCSelectorName(0), FakeRParens(0), > > StartsBinaryExpression(false), EndsBinaryExpression(false), > > LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false), > > - MatchingParen(NULL), Previous(NULL), Next(NULL), > > + IsForEachMacro(false), MatchingParen(NULL), Previous(NULL), > Next(NULL), > > Decision(FD_Unformatted), Finalized(false) {} > > > > /// \brief The \c Token. > > @@ -247,6 +247,9 @@ struct FormatToken { > > /// Only set if \c Type == \c TT_StartOfName. > > bool PartOfMultiVariableDeclStmt; > > > > + /// \brief Is this a foreach macro? > > + bool IsForEachMacro; > > + > > bool is(tok::TokenKind Kind) const { return Tok.is(Kind); } > > > > bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const { > > > > Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Format/TokenAnnotator.cpp (original) > > +++ cfe/trunk/lib/Format/TokenAnnotator.cpp Tue Apr 1 07:55:11 2014 > > @@ -120,6 +120,10 @@ private: > > Contexts.back().IsExpression = false; > > } else if (Left->Previous && > Left->Previous->is(tok::kw___attribute)) { > > Left->Type = TT_AttributeParen; > > + } else if (Left->Previous && Left->Previous->IsForEachMacro) { > > + // The first argument to a foreach macro is a declaration. > > + Contexts.back().IsForEachMacro = true; > > + Contexts.back().IsExpression = false; > > } > > > > if (StartsObjCMethodExpr) { > > @@ -464,6 +468,8 @@ private: > > Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = > true; > > if (Contexts.back().InCtorInitializer) > > Tok->Type = TT_CtorInitializerComma; > > + if (Contexts.back().IsForEachMacro) > > + Contexts.back().IsExpression = true; > > break; > > default: > > break; > > @@ -625,7 +631,7 @@ private: > > ColonIsObjCMethodExpr(false), FirstObjCSelectorName(NULL), > > FirstStartOfName(NULL), IsExpression(IsExpression), > > CanBeExpression(true), InTemplateArgument(false), > > - InCtorInitializer(false), CaretFound(false) {} > > + InCtorInitializer(false), CaretFound(false), > IsForEachMacro(false) {} > > > > tok::TokenKind ContextKind; > > unsigned BindingStrength; > > @@ -641,6 +647,7 @@ private: > > bool InTemplateArgument; > > bool InCtorInitializer; > > bool CaretFound; > > + bool IsForEachMacro; > > }; > > > > /// \brief Puts a new \c Context onto the stack \c Contexts for the > lifetime > > @@ -1408,8 +1415,9 @@ bool TokenAnnotator::spaceRequiredBetwee > > Left.isOneOf(tok::kw_return, tok::kw_new, tok::kw_delete, > > tok::semi) || > > (Style.SpaceBeforeParens != FormatStyle::SBPO_Never && > > - Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, > tok::kw_switch, > > - tok::kw_catch)) || > > + (Left.isOneOf(tok::kw_if, tok::kw_for, tok::kw_while, > > + tok::kw_switch, tok::kw_catch) || > > + Left.IsForEachMacro)) || > > (Style.SpaceBeforeParens == FormatStyle::SBPO_Always && > > Left.isOneOf(tok::identifier, tok::kw___attribute) && > > Line.Type != LT_PreprocessorDirective); > > > > Modified: cfe/trunk/lib/Format/UnwrappedLineParser.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/UnwrappedLineParser.cpp?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Format/UnwrappedLineParser.cpp (original) > > +++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp Tue Apr 1 07:55:11 2014 > > @@ -654,6 +654,12 @@ void UnwrappedLineParser::parseStructura > > return; > > } > > } > > + break; > > + case tok::identifier: > > + if (FormatTok->IsForEachMacro) { > > + parseForOrWhileLoop(); > > + return; > > + } > > // In all other cases, parse the declaration. > > break; > > default: > > @@ -1041,8 +1047,9 @@ void UnwrappedLineParser::parseNamespace > > } > > > > void UnwrappedLineParser::parseForOrWhileLoop() { > > - assert((FormatTok->Tok.is(tok::kw_for) || > FormatTok->Tok.is(tok::kw_while)) && > > - "'for' or 'while' expected"); > > + assert((FormatTok->Tok.is(tok::kw_for) || > FormatTok->Tok.is(tok::kw_while) || > > + FormatTok->IsForEachMacro) && > > + "'for', 'while' or foreach macro expected"); > > nextToken(); > > if (FormatTok->Tok.is(tok::l_paren)) > > parseParens(); > > > > Modified: cfe/trunk/unittests/Format/FormatTest.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=205307&r1=205306&r2=205307&view=diff > > > ============================================================================== > > --- cfe/trunk/unittests/Format/FormatTest.cpp (original) > > +++ cfe/trunk/unittests/Format/FormatTest.cpp Tue Apr 1 07:55:11 2014 > > @@ -465,6 +465,15 @@ TEST_F(FormatTest, RangeBasedForLoops) { > > " aaaaaaaaaaaa.aaaaaaaaaaaa().aaaaaaaaa().a()) > {\n}"); > > } > > > > +TEST_F(FormatTest, ForEachLoops) { > > + verifyFormat("void f() {\n" > > + " foreach (Item *item, itemlist) {}\n" > > + " Q_FOREACH (Item *item, itemlist) {}\n" > > + " BOOST_FOREACH (Item *item, itemlist) {}\n" > > + " UNKNOWN_FORACH(Item * item, itemlist) {}\n" > > + "}"); > > +} > > + > > TEST_F(FormatTest, FormatsWhileLoop) { > > verifyFormat("while (true) {\n}"); > > verifyFormat("while (true)\n" > > @@ -7607,6 +7616,13 @@ TEST_F(FormatTest, ParsesConfiguration) > > FormatStyle::NI_Inner); > > CHECK_PARSE("NamespaceIndentation: All", NamespaceIndentation, > > FormatStyle::NI_All); > > + > > + Style.ForEachMacros.clear(); > > + std::vector<std::string> BoostForeach = { "BOOST_FOREACH" }; > > + CHECK_PARSE("ForEachMacros: [BOOST_FOREACH]", ForEachMacros, > BoostForeach); > > + std::vector<std::string> BoostAndQForeach = { "BOOST_FOREACH", > "Q_FOREACH" }; > > + CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", > ForEachMacros, > > + BoostAndQForeach); > > } > > MSVC 2012 cannot use std::initializer_list, so the initialization of > the std::vector was causing the build bot to go red. I've fixed in > r205325. > > ~Aaron >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
