[clang] [clang] Ignore inline namespace for `hasName` (PR #109147)
Alejandro Álvarez Ayllón via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 10 07:19:24 PDT 2024
https://github.com/alejandro-alvarez-sonarsource updated https://github.com/llvm/llvm-project/pull/109147
>From d369d26aad940299eb98ff0c322614043144c558 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
<alejandro.alvarez at sonarsource.com>
Date: Mon, 24 Jul 2023 13:56:29 +0200
Subject: [PATCH 1/5] [clang] Ignore inline namespace for hasName
Add a new flag AlwaysSuppressInlineNamespace to PrintingPolicy that is
explicit about *always* removing inline namespaces regardless of
ambiguity.
Specializing a template from an inline namespace should be transparent
to said namespace. For instance
```
namespace foo {
inline namespace v1 {
template<typename A>
void function(A&);
}
}
namespace foo {
template<>
void function<int>(int&);
}
```
`hasName` should match both declarations of `foo::function`.
Makes the behavior of `matchesNodeFullSlow` and `matchesNodeFullFast`
consistent.
---
clang/include/clang/AST/PrettyPrinter.h | 11 +++++--
clang/lib/AST/Decl.cpp | 7 +++--
clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 1 +
.../ASTMatchers/ASTMatchersNarrowingTest.cpp | 29 +++++++++++++++++++
4 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 332ac3c6a004a9..a671211bf3ef93 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -61,9 +61,9 @@ struct PrintingPolicy {
SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
SuppressScope(false), SuppressUnwrittenScope(false),
SuppressInlineNamespace(true), SuppressElaboration(false),
- SuppressInitializers(false), ConstantArraySizeAsWritten(false),
- AnonymousTagLocations(true), SuppressStrongLifetime(false),
- SuppressLifetimeQualifiers(false),
+ AlwaysSuppressInlineNamespace(false), SuppressInitializers(false),
+ ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
+ SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false),
SuppressDefaultTemplateArgs(true), Bool(LO.Bool),
Nullptr(LO.CPlusPlus11 || LO.C23), NullptrTypeInNamespace(LO.CPlusPlus),
@@ -151,6 +151,11 @@ struct PrintingPolicy {
LLVM_PREFERRED_TYPE(bool)
unsigned SuppressElaboration : 1;
+ /// Suppress printing parts of scope specifiers that correspond
+ /// to inline namespaces, even if the name is ambiguous with the specifier
+ /// removed.
+ unsigned AlwaysSuppressInlineNamespace : 1;
+
/// Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a14b1b33d35efc..a3ac12d58ed044 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1737,8 +1737,11 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
continue;
// Suppress inline namespace if it doesn't make the result ambiguous.
- if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
- cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
+ if (Ctx->isInlineNamespace() && NameInScope &&
+ (P.AlwaysSuppressInlineNamespace ||
+ (P.SuppressInlineNamespace &&
+ cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(
+ NameInScope))))
continue;
// Skip non-named contexts such as linkage specifications and ExportDecls.
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 06309d327896b3..731fc97707eee7 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -656,6 +656,7 @@ bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {
PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
Policy.SuppressUnwrittenScope = SkipUnwritten;
Policy.SuppressInlineNamespace = SkipUnwritten;
+ Policy.AlwaysSuppressInlineNamespace = SkipUnwritten;
Node.printQualifiedName(OS, Policy);
const StringRef FullName = OS.str();
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 611e1f9ba5327c..d696375547acce 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2599,6 +2599,35 @@ TEST_P(ASTMatchersTest, HasName_MatchesInlinedNamespaces) {
EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C"))));
}
+TEST_P(ASTMatchersTest, HasName_MatchesSpecializedInlinedNamespace) {
+ if (!GetParam().isCXX11OrLater()) {
+ return;
+ }
+
+ StringRef code = R"(
+namespace a {
+ inline namespace v1 {
+ template<typename T> T foo(T);
+ }
+}
+
+namespace a {
+ enum Tag{T1, T2};
+
+ template <Tag, typename T> T foo(T);
+}
+
+auto v1 = a::foo(1);
+auto v2 = a::foo<a::T1>(1);
+)";
+ EXPECT_TRUE(matches(
+ code, varDecl(hasName("v1"), hasDescendant(callExpr(callee(
+ functionDecl(hasName("::a::foo"))))))));
+ EXPECT_TRUE(matches(
+ code, varDecl(hasName("v2"), hasDescendant(callExpr(callee(
+ functionDecl(hasName("::a::foo"))))))));
+}
+
TEST_P(ASTMatchersTest, HasName_MatchesAnonymousNamespaces) {
if (!GetParam().isCXX()) {
return;
>From bd40141da6702c2cf16b142b223e19d5b864c6e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
<alejandro.alvarez at sonarsource.com>
Date: Tue, 24 Sep 2024 08:46:45 +0200
Subject: [PATCH 2/5] Add release notes
---
clang/docs/ReleaseNotes.rst | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b47e06cb0c5d68..ccd3bbee1c2060 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -545,6 +545,9 @@ AST Matchers
- Fixed a crash when traverse lambda expr with invalid captures. (#GH106444)
+- Ensure hasName matches template specializations across inline namespaces,
+ making `matchesNodeFullSlow` and `matchesNodeFullFast` consistent.
+
clang-format
------------
>From 3bb9d07215e680bc65bb6c96cceed5a3d7c1f269 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
<alejandro.alvarez at sonarsource.com>
Date: Thu, 10 Oct 2024 10:28:45 +0200
Subject: [PATCH 3/5] Use an enum instead of two flags
---
clang/include/clang/AST/PrettyPrinter.h | 18 ++++++++----------
clang/lib/AST/Decl.cpp | 17 +++++++++++------
clang/lib/AST/TypePrinter.cpp | 4 +++-
clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 4 ++--
clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
clang/lib/CodeGen/CodeGenTypes.cpp | 2 +-
6 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index a671211bf3ef93..e36c72ffad135c 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -55,13 +55,15 @@ class PrintingCallbacks {
/// This type is intended to be small and suitable for passing by value.
/// It is very frequently copied.
struct PrintingPolicy {
+ enum class SupressInlineNamespaceMode : uint8_t { None, Redundant, All };
+
/// Create a default printing policy for the specified language.
PrintingPolicy(const LangOptions &LO)
: Indentation(2), SuppressSpecifiers(false),
SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
SuppressScope(false), SuppressUnwrittenScope(false),
- SuppressInlineNamespace(true), SuppressElaboration(false),
- AlwaysSuppressInlineNamespace(false), SuppressInitializers(false),
+ SuppressInlineNamespace(SupressInlineNamespaceMode::Redundant),
+ SuppressElaboration(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false),
@@ -141,21 +143,17 @@ struct PrintingPolicy {
unsigned SuppressUnwrittenScope : 1;
/// Suppress printing parts of scope specifiers that correspond
- /// to inline namespaces, where the name is unambiguous with the specifier
+ /// to inline namespaces.
+ /// If Redudant, where the name is unambiguous with the specifier removed.
+ /// If All, even if the name is ambiguous with the specifier
/// removed.
- LLVM_PREFERRED_TYPE(bool)
- unsigned SuppressInlineNamespace : 1;
+ SupressInlineNamespaceMode SuppressInlineNamespace : 2;
/// Ignore qualifiers and tag keywords as specified by elaborated type sugar,
/// instead letting the underlying type print as normal.
LLVM_PREFERRED_TYPE(bool)
unsigned SuppressElaboration : 1;
- /// Suppress printing parts of scope specifiers that correspond
- /// to inline namespaces, even if the name is ambiguous with the specifier
- /// removed.
- unsigned AlwaysSuppressInlineNamespace : 1;
-
/// Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index e29088ac7a1fea..d10d0be8db4719 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1737,12 +1737,17 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
continue;
// Suppress inline namespace if it doesn't make the result ambiguous.
- if (Ctx->isInlineNamespace() && NameInScope &&
- (P.AlwaysSuppressInlineNamespace ||
- (P.SuppressInlineNamespace &&
- cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(
- NameInScope))))
- continue;
+ if (Ctx->isInlineNamespace() && NameInScope) {
+ bool const isRedundant =
+ cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope);
+ if (P.SuppressInlineNamespace ==
+ PrintingPolicy::SupressInlineNamespaceMode::All ||
+ (P.SuppressInlineNamespace ==
+ PrintingPolicy::SupressInlineNamespaceMode::Redundant &&
+ isRedundant)) {
+ continue;
+ }
+ }
// Skip non-named contexts such as linkage specifications and ExportDecls.
const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index ca75bb97c158e1..fb31bd1c552a9c 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1413,7 +1413,9 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS,
// Only suppress an inline namespace if the name has the same lookup
// results in the enclosing namespace.
- if (Policy.SuppressInlineNamespace && NS->isInline() && NameInScope &&
+ if (Policy.SuppressInlineNamespace !=
+ PrintingPolicy::SupressInlineNamespaceMode::None &&
+ NS->isInline() && NameInScope &&
NS->isRedundantInlineQualifierFor(NameInScope))
return AppendScope(DC->getParent(), OS, NameInScope);
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 731fc97707eee7..45f3ab894d45d8 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -655,8 +655,8 @@ bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {
PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
Policy.SuppressUnwrittenScope = SkipUnwritten;
- Policy.SuppressInlineNamespace = SkipUnwritten;
- Policy.AlwaysSuppressInlineNamespace = SkipUnwritten;
+ Policy.SuppressInlineNamespace =
+ PrintingPolicy::SupressInlineNamespaceMode::All;
Node.printQualifiedName(OS, Policy);
const StringRef FullName = OS.str();
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 609957b75d6e7e..753f94b3a3a07f 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -287,7 +287,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.SplitTemplateClosers = true;
}
- PP.SuppressInlineNamespace = false;
+ PP.SuppressInlineNamespace = PrintingPolicy::SupressInlineNamespaceMode::None;
PP.PrintCanonicalTypes = true;
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 0b486a644f57b1..97b5597635baa6 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -60,7 +60,7 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
// example, we should probably enable PrintCanonicalTypes and
// FullyQualifiedNames.
PrintingPolicy Policy = RD->getASTContext().getPrintingPolicy();
- Policy.SuppressInlineNamespace = false;
+ Policy.SuppressInlineNamespace = PrintingPolicy::SupressInlineNamespaceMode::None;
// Name the codegen type after the typedef name
// if there is no tag type name available
>From a196be35ea77d1f2f78194f6d5899ed57030424a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
<alejandro.alvarez at sonarsource.com>
Date: Thu, 10 Oct 2024 13:45:48 +0200
Subject: [PATCH 4/5] Fix formatting
---
clang/lib/CodeGen/CodeGenTypes.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 97b5597635baa6..ed5386fe170cfc 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -60,7 +60,8 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
// example, we should probably enable PrintCanonicalTypes and
// FullyQualifiedNames.
PrintingPolicy Policy = RD->getASTContext().getPrintingPolicy();
- Policy.SuppressInlineNamespace = PrintingPolicy::SupressInlineNamespaceMode::None;
+ Policy.SuppressInlineNamespace =
+ PrintingPolicy::SupressInlineNamespaceMode::None;
// Name the codegen type after the typedef name
// if there is no tag type name available
>From 23837c6abb323e7e5d2fa6e893374de22f7f0039 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
<alejandro.alvarez at sonarsource.com>
Date: Thu, 10 Oct 2024 14:56:42 +0200
Subject: [PATCH 5/5] Fix regression and typo
---
clang/include/clang/AST/PrettyPrinter.h | 6 +++---
clang/lib/AST/Decl.cpp | 4 ++--
clang/lib/AST/TypePrinter.cpp | 2 +-
clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 3 ++-
clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
clang/lib/CodeGen/CodeGenTypes.cpp | 2 +-
6 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index e36c72ffad135c..695e28ebad1200 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -55,14 +55,14 @@ class PrintingCallbacks {
/// This type is intended to be small and suitable for passing by value.
/// It is very frequently copied.
struct PrintingPolicy {
- enum class SupressInlineNamespaceMode : uint8_t { None, Redundant, All };
+ enum class SuppressInlineNamespaceMode : uint8_t { None, Redundant, All };
/// Create a default printing policy for the specified language.
PrintingPolicy(const LangOptions &LO)
: Indentation(2), SuppressSpecifiers(false),
SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
SuppressScope(false), SuppressUnwrittenScope(false),
- SuppressInlineNamespace(SupressInlineNamespaceMode::Redundant),
+ SuppressInlineNamespace(SuppressInlineNamespaceMode::Redundant),
SuppressElaboration(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
@@ -147,7 +147,7 @@ struct PrintingPolicy {
/// If Redudant, where the name is unambiguous with the specifier removed.
/// If All, even if the name is ambiguous with the specifier
/// removed.
- SupressInlineNamespaceMode SuppressInlineNamespace : 2;
+ SuppressInlineNamespaceMode SuppressInlineNamespace : 2;
/// Ignore qualifiers and tag keywords as specified by elaborated type sugar,
/// instead letting the underlying type print as normal.
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index d10d0be8db4719..17ccb523e4862f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1741,9 +1741,9 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
bool const isRedundant =
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope);
if (P.SuppressInlineNamespace ==
- PrintingPolicy::SupressInlineNamespaceMode::All ||
+ PrintingPolicy::SuppressInlineNamespaceMode::All ||
(P.SuppressInlineNamespace ==
- PrintingPolicy::SupressInlineNamespaceMode::Redundant &&
+ PrintingPolicy::SuppressInlineNamespaceMode::Redundant &&
isRedundant)) {
continue;
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index fb31bd1c552a9c..008e87e7e5c14b 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1414,7 +1414,7 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS,
// Only suppress an inline namespace if the name has the same lookup
// results in the enclosing namespace.
if (Policy.SuppressInlineNamespace !=
- PrintingPolicy::SupressInlineNamespaceMode::None &&
+ PrintingPolicy::SuppressInlineNamespaceMode::None &&
NS->isInline() && NameInScope &&
NS->isRedundantInlineQualifierFor(NameInScope))
return AppendScope(DC->getParent(), OS, NameInScope);
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 45f3ab894d45d8..46dd44e6f2b24f 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -656,7 +656,8 @@ bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {
PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
Policy.SuppressUnwrittenScope = SkipUnwritten;
Policy.SuppressInlineNamespace =
- PrintingPolicy::SupressInlineNamespaceMode::All;
+ SkipUnwritten ? PrintingPolicy::SuppressInlineNamespaceMode::All
+ : PrintingPolicy::SuppressInlineNamespaceMode::None;
Node.printQualifiedName(OS, Policy);
const StringRef FullName = OS.str();
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 753f94b3a3a07f..25630d029b4bf8 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -287,7 +287,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.SplitTemplateClosers = true;
}
- PP.SuppressInlineNamespace = PrintingPolicy::SupressInlineNamespaceMode::None;
+ PP.SuppressInlineNamespace = PrintingPolicy::SuppressInlineNamespaceMode::None;
PP.PrintCanonicalTypes = true;
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index ed5386fe170cfc..339632090a5b71 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -61,7 +61,7 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
// FullyQualifiedNames.
PrintingPolicy Policy = RD->getASTContext().getPrintingPolicy();
Policy.SuppressInlineNamespace =
- PrintingPolicy::SupressInlineNamespaceMode::None;
+ PrintingPolicy::SuppressInlineNamespaceMode::None;
// Name the codegen type after the typedef name
// if there is no tag type name available
More information about the cfe-commits
mailing list