[clang] 467ad6a - [clang-format] Add support for absl nullability macros (#130346)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 14 00:01:38 PDT 2025
Author: Jan Voung
Date: 2025-03-14T00:01:35-07:00
New Revision: 467ad6a03583ba0566ec4f7c8ca4e2dabc60c8f6
URL: https://github.com/llvm/llvm-project/commit/467ad6a03583ba0566ec4f7c8ca4e2dabc60c8f6
DIFF: https://github.com/llvm/llvm-project/commit/467ad6a03583ba0566ec4f7c8ca4e2dabc60c8f6.diff
LOG: [clang-format] Add support for absl nullability macros (#130346)
Add support for formatting w/ absl nullability macros
(https://github.com/abseil/abseil-cpp/blob/c52afac4f87ef76e6293b84874e5126a62be1f15/absl/base/nullability.h#L237).
Example at https://godbolt.org/z/PYv19M1Gj
input:
```
std::vector<int* _Nonnull> x;
std::vector<int* absl_nonnull> y;
```
orig output:
```
std::vector<int* _Nonnull> x;
std::vector<int * absl_nonnull> y;
```
new output:
```
std::vector<int* _Nonnull> x;
std::vector<int* absl_nonnull> y;
```
credit to @ymand for the original patch
Added:
Modified:
clang/lib/Format/Format.cpp
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b5f1241321891..c67db4752e87b 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1713,6 +1713,10 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
FormatStyle::SIS_WithoutElse;
GoogleStyle.AllowShortLoopsOnASingleLine = true;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
+ // Abseil aliases to clang's `_Nonnull`, `_Nullable` and `_Null_unspecified`.
+ GoogleStyle.AttributeMacros.push_back("absl_nonnull");
+ GoogleStyle.AttributeMacros.push_back("absl_nullable");
+ GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
GoogleStyle.DerivePointerAlignment = true;
GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 273bab87b1ee1..cc42642f99252 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -909,6 +909,11 @@ TEST(ConfigParseTest, ParsesConfiguration) {
Style.AttributeMacros.clear();
CHECK_PARSE("BasedOnStyle: LLVM", AttributeMacros,
std::vector<std::string>{"__capability"});
+ CHECK_PARSE(
+ "BasedOnStyle: Google", AttributeMacros,
+ std::vector<std::string>({"__capability", "absl_nonnull", "absl_nullable",
+ "absl_nullability_unknown"}));
+ Style.AttributeMacros.clear();
CHECK_PARSE("AttributeMacros: [attr1, attr2]", AttributeMacros,
std::vector<std::string>({"attr1", "attr2"}));
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 6cd424c20720d..9864e7ec1b2ec 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -12375,6 +12375,9 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("vector<a *_Nonnull> v;");
verifyFormat("vector<a *_Nullable> v;");
verifyFormat("vector<a *_Null_unspecified> v;");
+ verifyGoogleFormat("vector<a* absl_nonnull> v;");
+ verifyGoogleFormat("vector<a* absl_nullable> v;");
+ verifyGoogleFormat("vector<a* absl_nullability_unknown> v;");
verifyFormat("vector<a *__ptr32> v;");
verifyFormat("vector<a *__ptr64> v;");
verifyFormat("vector<a *__capability> v;");
@@ -12518,6 +12521,12 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyIndependentOfContext("MACRO(A *_Nonnull a);");
verifyIndependentOfContext("MACRO(A *_Nullable a);");
verifyIndependentOfContext("MACRO(A *_Null_unspecified a);");
+
+ Style = getGoogleStyle();
+ verifyIndependentOfContext("MACRO(A* absl_nonnull a);", Style);
+ verifyIndependentOfContext("MACRO(A* absl_nullable a);", Style);
+ verifyIndependentOfContext("MACRO(A* absl_nullability_unknown a);", Style);
+
verifyIndependentOfContext("MACRO(A *__attribute__((foo)) a);");
verifyIndependentOfContext("MACRO(A *__attribute((foo)) a);");
verifyIndependentOfContext("MACRO(A *[[clang::attr]] a);");
@@ -12676,6 +12685,12 @@ TEST_F(FormatTest, UnderstandsAttributes) {
verifyFormat("SomeType s __unused{InitValue};", CustomAttrs);
verifyFormat("SomeType *__capability s(InitValue);", CustomAttrs);
verifyFormat("SomeType *__capability s{InitValue};", CustomAttrs);
+ verifyGoogleFormat("SomeType* absl_nonnull s(InitValue);");
+ verifyGoogleFormat("SomeType* absl_nonnull s{InitValue};");
+ verifyGoogleFormat("SomeType* absl_nullable s(InitValue);");
+ verifyGoogleFormat("SomeType* absl_nullable s{InitValue};");
+ verifyGoogleFormat("SomeType* absl_nullability_unknown s(InitValue);");
+ verifyGoogleFormat("SomeType* absl_nullability_unknown s{InitValue};");
}
TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {
@@ -12687,7 +12702,9 @@ TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {
verifyFormat("x = (foo *_Nonnull)*v;");
verifyFormat("x = (foo *_Nullable)*v;");
verifyFormat("x = (foo *_Null_unspecified)*v;");
- verifyFormat("x = (foo *_Nonnull)*v;");
+ verifyGoogleFormat("x = (foo* absl_nonnull)*v;");
+ verifyGoogleFormat("x = (foo* absl_nullable)*v;");
+ verifyGoogleFormat("x = (foo* absl_nullability_unknown)*v;");
verifyFormat("x = (foo *[[clang::attr]])*v;");
verifyFormat("x = (foo *[[clang::attr(\"foo\")]])*v;");
verifyFormat("x = (foo *__ptr32)*v;");
@@ -12701,7 +12718,7 @@ TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {
LongPointerLeft.PointerAlignment = FormatStyle::PAS_Left;
StringRef AllQualifiers =
"const volatile restrict __attribute__((foo)) _Nonnull _Null_unspecified "
- "_Nonnull [[clang::attr]] __ptr32 __ptr64 __capability";
+ "_Nullable [[clang::attr]] __ptr32 __ptr64 __capability";
verifyFormat(("x = (foo *" + AllQualifiers + ")*v;").str(), LongPointerRight);
verifyFormat(("x = (foo* " + AllQualifiers + ")*v;").str(), LongPointerLeft);
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index b44a369f77d92..5e2d301c5d1f3 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -3185,6 +3185,29 @@ TEST_F(TokenAnnotatorTest, UnderstandsAttributes) {
EXPECT_TOKEN(Tokens[5], tok::r_paren, TT_AttributeRParen);
}
+TEST_F(TokenAnnotatorTest, UnderstandsNullabilityAttributeMacros) {
+ // Under Google style, handles the Abseil macro aliases for the Clang
+ // nullability annotations.
+ auto Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ auto Tokens = annotate("x = (foo* absl_nullable)*v;", Style);
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[4], tok::star, TT_PointerOrReference);
+ EXPECT_TOKEN(Tokens[5], tok::identifier, TT_AttributeMacro);
+ EXPECT_TOKEN(Tokens[7], tok::star, TT_UnaryOperator);
+
+ Tokens = annotate("x = (foo* absl_nonnull)*v;", Style);
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[4], tok::star, TT_PointerOrReference);
+ EXPECT_TOKEN(Tokens[5], tok::identifier, TT_AttributeMacro);
+ EXPECT_TOKEN(Tokens[7], tok::star, TT_UnaryOperator);
+
+ Tokens = annotate("x = (foo* absl_nullability_unknown)*v;", Style);
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[4], tok::star, TT_PointerOrReference);
+ EXPECT_TOKEN(Tokens[5], tok::identifier, TT_AttributeMacro);
+ EXPECT_TOKEN(Tokens[7], tok::star, TT_UnaryOperator);
+}
+
TEST_F(TokenAnnotatorTest, UnderstandsControlStatements) {
auto Tokens = annotate("while (true) {}");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
More information about the cfe-commits
mailing list