[clang] 9e27f38 - [clang-format] Add a SpaceAroundPointerQualifiers style option
Alex Richardson via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 18 10:47:15 PDT 2020
Author: Alex Richardson
Date: 2020-10-18T18:17:50+01:00
New Revision: 9e27f38354e850346f5f4e895e44ad3346546d9c
URL: https://github.com/llvm/llvm-project/commit/9e27f38354e850346f5f4e895e44ad3346546d9c
DIFF: https://github.com/llvm/llvm-project/commit/9e27f38354e850346f5f4e895e44ad3346546d9c.diff
LOG: [clang-format] Add a SpaceAroundPointerQualifiers style option
Some projects (e.g. FreeBSD) align pointers to the right but expect a
space between the '*' and any pointer qualifiers such as const. To handle
these cases this patch adds a new config option SpaceAroundPointerQualifiers
that can be used to configure whether spaces need to be added before/after
pointer qualifiers.
PointerAlignment = Right
SpaceAroundPointerQualifiers = Default/After:
void *const *x = NULL;
SpaceAroundPointerQualifiers = Before/Both
void * const *x = NULL;
PointerAlignment = Left
SpaceAroundPointerQualifiers = Default/Before:
void* const* x = NULL;
SpaceAroundPointerQualifiers = After/Both
void* const * x = NULL;
PointerAlignment = Middle
SpaceAroundPointerQualifiers = Default/Before/After/Both:
void * const * x = NULL;
Reviewed By: MyDeveloperDay
Differential Revision: https://reviews.llvm.org/D88227
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 0c3ed9f4ab84..ccc59cd6fc19 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -2463,6 +2463,46 @@ the configuration (without a prefix: ``Auto``).
true: false:
template <int> void foo(); vs. template<int> void foo();
+**SpaceAroundPointerQualifiers** (``SpaceAroundPointerQualifiersStyle``)
+ Defines in which cases to put a space before or after pointer qualifiers
+
+ Possible values:
+
+ * ``SAPQ_Default`` (in configuration: ``Default``)
+ Don't ensure spaces around pointer qualifiers and use PointerAlignment
+ instead.
+
+ .. code-block:: c++
+
+ PointerAlignment: Left PointerAlignment: Right
+ void* const* x = NULL; vs. void *const *x = NULL;
+
+ * ``SAPQ_Before`` (in configuration: ``Before``)
+ Ensure that there is a space before pointer qualifiers.
+
+ .. code-block:: c++
+
+ PointerAlignment: Left PointerAlignment: Right
+ void* const* x = NULL; vs. void * const *x = NULL;
+
+ * ``SAPQ_After`` (in configuration: ``After``)
+ Ensure that there is a space after pointer qualifiers.
+
+ .. code-block:: c++
+
+ PointerAlignment: Left PointerAlignment: Right
+ void* const * x = NULL; vs. void *const *x = NULL;
+
+ * ``SAPQ_Both`` (in configuration: ``Both``)
+ Ensure that there is a space both before and after pointer qualifiers.
+
+ .. code-block:: c++
+
+ PointerAlignment: Left PointerAlignment: Right
+ void* const * x = NULL; vs. void * const *x = NULL;
+
+
+
**SpaceBeforeAssignmentOperators** (``bool``)
If ``false``, spaces will be removed before assignment operators.
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 40d5184f4d0d..587e588525df 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2078,6 +2078,38 @@ struct FormatStyle {
/// \endcode
bool SpaceAfterTemplateKeyword;
+ /// Different ways to put a space before opening parentheses.
+ enum SpaceAroundPointerQualifiersStyle {
+ /// Don't ensure spaces around pointer qualifiers and use PointerAlignment
+ /// instead.
+ /// \code
+ /// PointerAlignment: Left PointerAlignment: Right
+ /// void* const* x = NULL; vs. void *const *x = NULL;
+ /// \endcode
+ SAPQ_Default,
+ /// Ensure that there is a space before pointer qualifiers.
+ /// \code
+ /// PointerAlignment: Left PointerAlignment: Right
+ /// void* const* x = NULL; vs. void * const *x = NULL;
+ /// \endcode
+ SAPQ_Before,
+ /// Ensure that there is a space after pointer qualifiers.
+ /// \code
+ /// PointerAlignment: Left PointerAlignment: Right
+ /// void* const * x = NULL; vs. void *const *x = NULL;
+ /// \endcode
+ SAPQ_After,
+ /// Ensure that there is a space both before and after pointer qualifiers.
+ /// \code
+ /// PointerAlignment: Left PointerAlignment: Right
+ /// void* const * x = NULL; vs. void * const *x = NULL;
+ /// \endcode
+ SAPQ_Both,
+ };
+
+ /// Defines in which cases to put a space before or after pointer qualifiers
+ SpaceAroundPointerQualifiersStyle SpaceAroundPointerQualifiers;
+
/// If ``false``, spaces will be removed before assignment operators.
/// \code
/// true: false:
@@ -2470,6 +2502,7 @@ struct FormatStyle {
R.SpaceBeforeCtorInitializerColon &&
SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon &&
SpaceBeforeParens == R.SpaceBeforeParens &&
+ SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers &&
SpaceBeforeRangeBasedForLoopColon ==
R.SpaceBeforeRangeBasedForLoopColon &&
SpaceInEmptyBlock == R.SpaceInEmptyBlock &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index f2215e255c2b..1c566c9ea49d 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -347,6 +347,17 @@ template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
+ IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
+ IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
+ IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
+ IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
static void enumeration(IO &IO,
@@ -598,6 +609,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceBeforeInheritanceColon",
Style.SpaceBeforeInheritanceColon);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
+ IO.mapOptional("SpaceAroundPointerQualifiers",
+ Style.SpaceAroundPointerQualifiers);
IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
Style.SpaceBeforeRangeBasedForLoopColon);
IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
@@ -935,6 +948,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceAfterCStyleCast = false;
LLVMStyle.SpaceAfterLogicalNot = false;
LLVMStyle.SpaceAfterTemplateKeyword = true;
+ LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
LLVMStyle.SpaceBeforeInheritanceColon = true;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 2fa3b28f3a39..66a8cacbb4af 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2859,6 +2859,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (!TokenBeforeMatchingParen || !Left.is(TT_TypeDeclarationParen))
return true;
}
+ // Add a space if the previous token is a pointer qualifer or the closing
+ // parenthesis of __attribute__(()) expression and the style requires spaces
+ // after pointer qualifiers.
+ if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_After ||
+ Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
+ (Left.is(TT_AttributeParen) || Left.canBePointerOrReferenceQualifier()))
+ return true;
return (Left.Tok.isLiteral() ||
(!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Left ||
@@ -2871,7 +2878,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
(Style.PointerAlignment != FormatStyle::PAS_Right &&
!Line.IsMultiVariableDeclStmt)))
return true;
- if (Left.is(TT_PointerOrReference))
+ if (Left.is(TT_PointerOrReference)) {
+ // Add a space if the next token is a pointer qualifer and the style
+ // requires spaces before pointer qualifiers.
+ if ((Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Before ||
+ Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
+ Right.canBePointerOrReferenceQualifier())
+ return true;
return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
(Right.isOneOf(Keywords.kw_override, Keywords.kw_final) &&
!Right.is(TT_StartOfName)) ||
@@ -2883,6 +2896,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Left.Previous &&
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon,
tok::l_square));
+ }
// Ensure right pointer alignement with ellipsis e.g. int *...P
if (Left.is(tok::ellipsis) && Left.Previous &&
Left.Previous->isOneOf(tok::star, tok::amp, tok::ampamp))
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 7686e252f7c2..1bdd7062fbb8 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -12104,6 +12104,80 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeColon) {
NoSpaceStyle);
}
+TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) {
+ FormatStyle Style = getLLVMStyle();
+
+ Style.PointerAlignment = FormatStyle::PAS_Left;
+ Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
+ verifyFormat("void* const* x = NULL;", Style);
+
+#define verifyQualifierSpaces(Code, Pointers, Qualifiers) \
+ do { \
+ Style.PointerAlignment = FormatStyle::Pointers; \
+ Style.SpaceAroundPointerQualifiers = FormatStyle::Qualifiers; \
+ verifyFormat(Code, Style); \
+ } while (false)
+
+ verifyQualifierSpaces("void* const* x = NULL;", PAS_Left, SAPQ_Default);
+ verifyQualifierSpaces("void *const *x = NULL;", PAS_Right, SAPQ_Default);
+ verifyQualifierSpaces("void * const * x = NULL;", PAS_Middle, SAPQ_Default);
+
+ verifyQualifierSpaces("void* const* x = NULL;", PAS_Left, SAPQ_Before);
+ verifyQualifierSpaces("void * const *x = NULL;", PAS_Right, SAPQ_Before);
+ verifyQualifierSpaces("void * const * x = NULL;", PAS_Middle, SAPQ_Before);
+
+ verifyQualifierSpaces("void* const * x = NULL;", PAS_Left, SAPQ_After);
+ verifyQualifierSpaces("void *const *x = NULL;", PAS_Right, SAPQ_After);
+ verifyQualifierSpaces("void * const * x = NULL;", PAS_Middle, SAPQ_After);
+
+ verifyQualifierSpaces("void* const * x = NULL;", PAS_Left, SAPQ_Both);
+ verifyQualifierSpaces("void * const *x = NULL;", PAS_Right, SAPQ_Both);
+ verifyQualifierSpaces("void * const * x = NULL;", PAS_Middle, SAPQ_Both);
+
+#undef verifyQualifierSpaces
+
+ FormatStyle Spaces = getLLVMStyle();
+ Spaces.AttributeMacros.push_back("qualified");
+ Spaces.PointerAlignment = FormatStyle::PAS_Right;
+ Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
+ verifyFormat("SomeType *volatile *a = NULL;", Spaces);
+ verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces);
+ verifyFormat("std::vector<SomeType *const *> x;", Spaces);
+ verifyFormat("std::vector<SomeType *qualified *> x;", Spaces);
+ verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
+ Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Before;
+ verifyFormat("SomeType * volatile *a = NULL;", Spaces);
+ verifyFormat("SomeType * __attribute__((attr)) *a = NULL;", Spaces);
+ verifyFormat("std::vector<SomeType * const *> x;", Spaces);
+ verifyFormat("std::vector<SomeType * qualified *> x;", Spaces);
+ verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
+
+ // Check that SAPQ_Before doesn't result in extra spaces for PAS_Left.
+ Spaces.PointerAlignment = FormatStyle::PAS_Left;
+ Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Before;
+ verifyFormat("SomeType* volatile* a = NULL;", Spaces);
+ verifyFormat("SomeType* __attribute__((attr))* a = NULL;", Spaces);
+ verifyFormat("std::vector<SomeType* const*> x;", Spaces);
+ verifyFormat("std::vector<SomeType* qualified*> x;", Spaces);
+ verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
+ // However, setting it to SAPQ_After should add spaces after __attribute, etc.
+ Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_After;
+ verifyFormat("SomeType* volatile * a = NULL;", Spaces);
+ verifyFormat("SomeType* __attribute__((attr)) * a = NULL;", Spaces);
+ verifyFormat("std::vector<SomeType* const *> x;", Spaces);
+ verifyFormat("std::vector<SomeType* qualified *> x;", Spaces);
+ verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
+
+ // PAS_Middle should not have any noticeable changes even for SAPQ_Both
+ Spaces.PointerAlignment = FormatStyle::PAS_Middle;
+ Spaces.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_After;
+ verifyFormat("SomeType * volatile * a = NULL;", Spaces);
+ verifyFormat("SomeType * __attribute__((attr)) * a = NULL;", Spaces);
+ verifyFormat("std::vector<SomeType * const *> x;", Spaces);
+ verifyFormat("std::vector<SomeType * qualified *> x;", Spaces);
+ verifyFormat("std::vector<SomeVar * NotAQualifier> x;", Spaces);
+}
+
TEST_F(FormatTest, AlignConsecutiveMacros) {
FormatStyle Style = getLLVMStyle();
Style.AlignConsecutiveAssignments = true;
@@ -14194,6 +14268,16 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("AllowShortFunctionsOnASingleLine: true",
AllowShortFunctionsOnASingleLine, FormatStyle::SFS_All);
+ Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Both;
+ CHECK_PARSE("SpaceAroundPointerQualifiers: Default",
+ SpaceAroundPointerQualifiers, FormatStyle::SAPQ_Default);
+ CHECK_PARSE("SpaceAroundPointerQualifiers: Before",
+ SpaceAroundPointerQualifiers, FormatStyle::SAPQ_Before);
+ CHECK_PARSE("SpaceAroundPointerQualifiers: After",
+ SpaceAroundPointerQualifiers, FormatStyle::SAPQ_After);
+ CHECK_PARSE("SpaceAroundPointerQualifiers: Both",
+ SpaceAroundPointerQualifiers, FormatStyle::SAPQ_Both);
+
Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
CHECK_PARSE("SpaceBeforeParens: Never", SpaceBeforeParens,
FormatStyle::SBPO_Never);
More information about the cfe-commits
mailing list