r205307 - clang-format: Support configurable list of foreach-macros.
Aaron Ballman
aaron at aaronballman.com
Tue Apr 1 09:37:58 PDT 2014
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
More information about the cfe-commits
mailing list