Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1673,6 +1673,22 @@ /// \brief The number of columns used for tab stops. unsigned TabWidth; + /// \brief A vector of macros that should be interpreted as string wrapping + /// macros instead of as function calls. + /// + /// These are expected to be macros of the form: + /// \code + /// _T("...some string...") + /// \endcode + /// + /// In the .clang-format configuration file, this can be configured like: + /// \code{.yaml} + /// TMarcos: ['_T', 'myT'] + /// \endcode + /// + /// For example: _T. + std::vector TMacros; + /// \brief Different ways to use tab in formatting. enum UseTabStyle { /// Never use tab. @@ -1781,7 +1797,7 @@ SpacesInParentheses == R.SpacesInParentheses && SpacesInSquareBrackets == R.SpacesInSquareBrackets && Standard == R.Standard && TabWidth == R.TabWidth && - UseTab == R.UseTab; + TMacros == R.TMacros && UseTab == R.UseTab; } llvm::Optional GetLanguageStyle(LanguageKind Language) const; Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -430,6 +430,7 @@ IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); IO.mapOptional("Standard", Style.Standard); IO.mapOptional("TabWidth", Style.TabWidth); + IO.mapOptional("TMacros", Style.TMacros); IO.mapOptional("UseTab", Style.UseTab); } }; @@ -686,6 +687,7 @@ LLVMStyle.DisableFormat = false; LLVMStyle.SortIncludes = true; LLVMStyle.SortUsingDeclarations = true; + LLVMStyle.TMacros.push_back("_T"); return LLVMStyle; } Index: lib/Format/FormatTokenLexer.cpp =================================================================== --- lib/Format/FormatTokenLexer.cpp +++ lib/Format/FormatTokenLexer.cpp @@ -368,7 +368,8 @@ return false; FormatToken *Macro = Tokens[Tokens.size() - 4]; - if (Macro->TokenText.empty() || !String->TokenText.startswith("\"") || !String->TokenText.endswith("\"")) + if (std::find(Style.TMacros.begin(), Style.TMacros.end(), Macro->TokenText) == + Style.TMacros.end()) return false; const char *Start = Macro->TokenText.data(); Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -7937,6 +7937,7 @@ TEST_F(FormatTest, BreaksStringLiteralsWithin_GenericTMacro) { FormatStyle Style = getLLVMStyleWithColumns(25); + Style.TMacros.push_back("blablaT"); EXPECT_EQ( "blablaT(\"aaaaaaaaaaaaaa\")\n" "blablaT(\"aaaaaaaaaaaaaa\")\n" @@ -10688,6 +10689,17 @@ " - 'CPPEVAL'\n" " CanonicalDelimiter: 'cc'", RawStringFormats, ExpectedRawStringFormats); + + // FIXME: This is required because parsing a configuration simply overwrites + // the first N elements of the list instead of resetting it. + Style.TMacros.clear(); + std::vector TestTMarco; + TestTMarco.push_back("_T"); + CHECK_PARSE("TMacros: [_T]", TMacros, TestTMarco); + std::vector TestTMarcoAndMyT; + TestTMarcoAndMyT.push_back("_T"); + TestTMarcoAndMyT.push_back("myT"); + CHECK_PARSE("TMacros: [_T, myT]", TMacros, TestTMarcoAndMyT); } TEST_F(FormatTest, ParsesConfigurationWithLanguages) {