r361986 - [clang-format] Allow configuring list of function-like macros that resolve to a type
Francois Ferrand via cfe-commits
cfe-commits at lists.llvm.org
Wed May 29 09:30:48 PDT 2019
Author: typz
Date: Wed May 29 09:30:47 2019
New Revision: 361986
URL: http://llvm.org/viewvc/llvm-project?rev=361986&view=rev
Log:
[clang-format] Allow configuring list of function-like macros that resolve to a type
Summary:
Adds a `TypenameMacros` configuration option that causes certain identifiers to be handled in a way similar to `typeof()`.
This is enough to:
- Prevent misinterpreting declarations of pointers to such types as expressions (`STACK_OF(int) * foo` -> `STACK_OF(int) *foo`),
- Avoid surprising line breaks in variable/struct field declarations (`STACK_OF(int)\nfoo;` -> `STACK_OF(int) foo;`, see https://bugs.llvm.org/show_bug.cgi?id=30353).
Reviewers: Typz, krasimir, djasper
Reviewed By: Typz
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D57184
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/FormatTokenLexer.cpp
cfe/trunk/lib/Format/TokenAnnotator.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=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/docs/ClangFormatStyleOptions.rst (original)
+++ cfe/trunk/docs/ClangFormatStyleOptions.rst Wed May 29 09:30:47 2019
@@ -1367,6 +1367,24 @@ the configuration (without a prefix: ``A
For example: BOOST_FOREACH.
+**TypenameMacros** (``std::vector<std::string>``)
+ A vector of macros that should be interpreted as type declarations
+ instead of as function calls.
+
+ These are expected to be macros of the form:
+
+ .. code-block: c++
+
+ STACK_OF(...)
+
+ In the .clang-format configuration file, this can be configured like:
+
+ .. code-block: yaml
+
+ TypenameMacros: ['STACK_OF', 'LIST']
+
+ For example: OpenSSL STACK_OF, BSD LIST_ENTRY.
+
**IncludeBlocks** (``IncludeBlocksStyle``)
Dependent on the value, multiple ``#include`` blocks can be sorted
as one and divided based on category.
Modified: cfe/trunk/include/clang/Format/Format.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/include/clang/Format/Format.h (original)
+++ cfe/trunk/include/clang/Format/Format.h Wed May 29 09:30:47 2019
@@ -1160,6 +1160,22 @@ struct FormatStyle {
/// For example: BOOST_FOREACH.
std::vector<std::string> ForEachMacros;
+ /// \brief A vector of macros that should be interpreted as type declarations
+ /// instead of as function calls.
+ ///
+ /// These are expected to be macros of the form:
+ /// \code
+ /// STACK_OF(...)
+ /// \endcode
+ ///
+ /// In the .clang-format configuration file, this can be configured like:
+ /// \code{.yaml}
+ /// TypenameMacros: ['STACK_OF', 'LIST']
+ /// \endcode
+ ///
+ /// For example: OpenSSL STACK_OF, BSD LIST_ENTRY.
+ std::vector<std::string> TypenameMacros;
+
/// A vector of macros that should be interpreted as complete
/// statements.
///
@@ -1952,7 +1968,8 @@ struct FormatStyle {
SpacesInParentheses == R.SpacesInParentheses &&
SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
Standard == R.Standard && TabWidth == R.TabWidth &&
- StatementMacros == R.StatementMacros && UseTab == R.UseTab;
+ StatementMacros == R.StatementMacros && UseTab == R.UseTab &&
+ TypenameMacros == R.TypenameMacros;
}
llvm::Optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const;
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed May 29 09:30:47 2019
@@ -505,6 +505,7 @@ template <> struct MappingTraits<FormatS
IO.mapOptional("Standard", Style.Standard);
IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TabWidth", Style.TabWidth);
+ IO.mapOptional("TypenameMacros", Style.TypenameMacros);
IO.mapOptional("UseTab", Style.UseTab);
}
};
Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Wed May 29 09:30:47 2019
@@ -96,6 +96,7 @@ namespace format {
TYPE(TrailingAnnotation) \
TYPE(TrailingReturnArrow) \
TYPE(TrailingUnaryOperator) \
+ TYPE(TypenameMacro) \
TYPE(UnaryOperator) \
TYPE(CSharpStringLiteral) \
TYPE(CSharpNullCoalescing) \
Modified: cfe/trunk/lib/Format/FormatTokenLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.cpp?rev=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatTokenLexer.cpp (original)
+++ cfe/trunk/lib/Format/FormatTokenLexer.cpp Wed May 29 09:30:47 2019
@@ -39,6 +39,8 @@ FormatTokenLexer::FormatTokenLexer(const
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 &TypenameMacro : Style.TypenameMacros)
+ Macros.insert({&IdentTable.get(TypenameMacro), TT_TypenameMacro});
}
ArrayRef<FormatToken *> FormatTokenLexer::lex() {
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed May 29 09:30:47 2019
@@ -1194,11 +1194,12 @@ private:
// Reset token type in case we have already looked at it and then
// recovered from an error (e.g. failure to find the matching >).
- if (!CurrentToken->isOneOf(
- TT_LambdaLSquare, TT_LambdaLBrace, TT_ForEachMacro,
- TT_FunctionLBrace, TT_ImplicitStringLiteral, TT_InlineASMBrace,
- TT_JsFatArrow, TT_LambdaArrow, TT_OverloadedOperator,
- TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral))
+ if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_LambdaLBrace,
+ TT_ForEachMacro, TT_TypenameMacro,
+ TT_FunctionLBrace, TT_ImplicitStringLiteral,
+ TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
+ TT_OverloadedOperator, TT_RegexLiteral,
+ TT_TemplateString, TT_ObjCStringLiteral))
CurrentToken->Type = TT_Unknown;
CurrentToken->Role.reset();
CurrentToken->MatchingParen = nullptr;
@@ -1416,6 +1417,7 @@ private:
if (AfterParen->Tok.isNot(tok::caret)) {
if (FormatToken *BeforeParen = Current.MatchingParen->Previous)
if (BeforeParen->is(tok::identifier) &&
+ !BeforeParen->is(TT_TypenameMacro) &&
BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
(!BeforeParen->Previous ||
BeforeParen->Previous->ClosesTemplateDeclaration))
@@ -1667,7 +1669,8 @@ private:
FormatToken *TokenBeforeMatchingParen =
PrevToken->MatchingParen->getPreviousNonComment();
if (TokenBeforeMatchingParen &&
- TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype))
+ TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype,
+ TT_TypenameMacro))
return TT_PointerOrReference;
}
@@ -2527,7 +2530,8 @@ bool TokenAnnotator::spaceRequiredBetwee
FormatToken *TokenBeforeMatchingParen =
Left.MatchingParen->getPreviousNonComment();
if (!TokenBeforeMatchingParen ||
- !TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype))
+ !TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype,
+ TT_TypenameMacro))
return true;
}
return (Left.Tok.isLiteral() ||
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=361986&r1=361985&r2=361986&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Wed May 29 09:30:47 2019
@@ -13545,6 +13545,35 @@ TEST_F(FormatTest, GuessLanguageWithChil
guessLanguage("foo.h", "#define FOO ({ foo(); ({ NSString *s; }) })"));
}
+TEST_F(FormatTest, TypenameMacros) {
+ std::vector<std::string> TypenameMacros = {"STACK_OF", "LIST", "TAILQ_ENTRY"};
+
+ // Test case reported in https://bugs.llvm.org/show_bug.cgi?id=30353
+ FormatStyle Google = getGoogleStyleWithColumns(0);
+ Google.TypenameMacros = TypenameMacros;
+ verifyFormat("struct foo {\n"
+ " int bar;\n"
+ " TAILQ_ENTRY(a) bleh;\n"
+ "};", Google);
+
+ FormatStyle Macros = getLLVMStyle();
+ Macros.TypenameMacros = TypenameMacros;
+
+ verifyFormat("STACK_OF(int) a;", Macros);
+ verifyFormat("STACK_OF(int) *a;", Macros);
+ verifyFormat("STACK_OF(int const *) *a;", Macros);
+ verifyFormat("STACK_OF(int *const) *a;", Macros);
+ verifyFormat("STACK_OF(int, string) a;", Macros);
+ verifyFormat("STACK_OF(LIST(int)) a;", Macros);
+ verifyFormat("STACK_OF(LIST(int)) a, b;", Macros);
+ verifyFormat("for (LIST(int) *a = NULL; a;) {\n}", Macros);
+ verifyFormat("STACK_OF(int) f(LIST(int) *arg);", Macros);
+
+ Macros.PointerAlignment = FormatStyle::PAS_Left;
+ verifyFormat("STACK_OF(int)* a;", Macros);
+ verifyFormat("STACK_OF(int*)* a;", Macros);
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
More information about the cfe-commits
mailing list