r205307 - clang-format: Support configurable list of foreach-macros.

Daniel Jasper djasper at google.com
Tue Apr 1 13:24:59 PDT 2014


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 <aaron at aaronballman.com>wrote:

> On Tue, Apr 1, 2014 at 8:55 AM, Daniel Jasper <djasper at google.com> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140401/3f3c930a/attachment.html>


More information about the cfe-commits mailing list