Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -1296,6 +1296,16 @@ /// For example: Q_UNUSED std::vector StatementMacros; + /// A vector of macros that should not be included in the following named + /// nested specifier. + /// + /// Global specifier '::' must not be merged with the preceding identifier, + /// specifically macros. This allows clang-format to be aware of those + /// macros. + /// + /// For example: ALWAYS_INLINE + std::vector KeywordMacros; + /// A vector of macros which are used to open namespace blocks. /// /// These are expected to be macros of the form: @@ -2161,7 +2171,8 @@ SpacesInSquareBrackets == R.SpacesInSquareBrackets && SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets && Standard == R.Standard && TabWidth == R.TabWidth && - StatementMacros == R.StatementMacros && UseTab == R.UseTab && + StatementMacros == R.StatementMacros && + KeywordMacros == R.KeywordMacros && UseTab == R.UseTab && UseCRLF == R.UseCRLF && TypenameMacros == R.TypenameMacros; } Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -547,6 +547,7 @@ Style.SpaceBeforeSquareBrackets); IO.mapOptional("Standard", Style.Standard); IO.mapOptional("StatementMacros", Style.StatementMacros); + IO.mapOptional("KeywordMacros", Style.KeywordMacros); IO.mapOptional("TabWidth", Style.TabWidth); IO.mapOptional("TypenameMacros", Style.TypenameMacros); IO.mapOptional("UseCRLF", Style.UseCRLF); Index: clang/lib/Format/FormatToken.h =================================================================== --- clang/lib/Format/FormatToken.h +++ clang/lib/Format/FormatToken.h @@ -66,6 +66,7 @@ TYPE(JsTypeColon) \ TYPE(JsTypeOperator) \ TYPE(JsTypeOptionalQuestion) \ + TYPE(KeywordMacro) \ TYPE(LambdaArrow) \ TYPE(LambdaLBrace) \ TYPE(LambdaLSquare) \ Index: clang/lib/Format/FormatTokenLexer.cpp =================================================================== --- clang/lib/Format/FormatTokenLexer.cpp +++ clang/lib/Format/FormatTokenLexer.cpp @@ -39,6 +39,8 @@ Macros.insert({&IdentTable.get(ForEachMacro), TT_ForEachMacro}); for (const std::string &StatementMacro : Style.StatementMacros) Macros.insert({&IdentTable.get(StatementMacro), TT_StatementMacro}); + for (const std::string &KeywordMacro : Style.KeywordMacros) + Macros.insert({&IdentTable.get(KeywordMacro), TT_KeywordMacro}); for (const std::string &TypenameMacro : Style.TypenameMacros) Macros.insert({&IdentTable.get(TypenameMacro), TT_TypenameMacro}); for (const std::string &NamespaceMacro : Style.NamespaceMacros) Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1227,8 +1227,8 @@ TT_LambdaLSquare, TT_LambdaLBrace, TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace, TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow, TT_NamespaceMacro, - TT_OverloadedOperator, TT_RegexLiteral, TT_TemplateString, - TT_ObjCStringLiteral)) + TT_KeywordMacro, TT_OverloadedOperator, TT_RegexLiteral, + TT_TemplateString, TT_ObjCStringLiteral)) CurrentToken->Type = TT_Unknown; CurrentToken->Role.reset(); CurrentToken->MatchingParen = nullptr; @@ -3039,10 +3039,7 @@ (Left.is(tok::identifier) || Left.is(tok::kw_this))) return false; if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) - // Generally don't remove existing spaces between an identifier and "::". - // The identifier might actually be a macro name such as ALWAYS_INLINE. If - // this turns out to be too lenient, add analysis of the identifier itself. - return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd(); + return Left.is(TT_KeywordMacro); if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment)) return (Left.is(TT_TemplateOpener) && Style.Standard < FormatStyle::LS_Cpp11) || Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -159,7 +159,10 @@ verifyFormat("::ns::SomeFunction(::ns::SomeOtherFunction())"); verifyFormat("static constexpr bool Bar = decltype(bar())::value;"); verifyFormat("bool a = 2 < ::SomeFunction();"); - verifyFormat("ALWAYS_INLINE ::std::string getName();"); + EXPECT_EQ("bool ns::Function()", format("bool ns :: Function()")); + FormatStyle Style = getLLVMStyle(); + Style.KeywordMacros.push_back("ALWAYS_INLINE"); + verifyFormat("ALWAYS_INLINE ::std::string getName();", Style); verifyFormat("some::string getName();"); }