[clang-tools-extra] Revert clang-doc arena merging patches (PR #191668)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Apr 11 14:35:05 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Paul Kirth (ilovepi)
<details>
<summary>Changes</summary>
This is a set of squashed reverts of recen clang doc patches, since its
breaking something on Darwin builders:
https://lab.llvm.org/buildbot/#/builders/23/builds/19172
Revert "[clang-doc][nfc] Default initialize all StringRef members (#<!-- -->191641)"
This reverts commit 155b9b354c1d91661be9f6d0432a96e47cfc2700.
Revert "[clang-doc] Initialize StringRef members in Info types (#<!-- -->191637)"
This reverts commit 489dab3827b255d21ea38b1e3f45ddb08bd10a87.
Revert "[clang-doc] Initialize member variable (#<!-- -->191570)"
This reverts commit 5d64a44a84af31f9e99d42cccffa4f01c0be2e0b.
Revert "[clang-doc] Merge data into persistent memory (#<!-- -->190056)"
This reverts commit 21e0034c69489eff3b09929e5e13ea34b3dd0e5a.
Revert "[clang-doc] Support deep copy between arenas for merging (#<!-- -->190055)"
This reverts commit c70dae8b0cee46af1411bc4e4ba6fc28e2babf3e.
---
Patch is 30.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191668.diff
3 Files Affected:
- (modified) clang-tools-extra/clang-doc/Representation.cpp (+29-272)
- (modified) clang-tools-extra/clang-doc/Representation.h (+23-60)
- (modified) clang-tools-extra/clang-doc/tool/ClangDocMain.cpp (+25-25)
``````````diff
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 50c5f9bb1d071..1f01169b4c638 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -115,32 +115,7 @@ static void reduceChildren(llvm::simple_ilist<T> &Children,
auto It = llvm::find_if(
Children, [&](const T &C) { return C.USR == ChildToMerge->USR; });
if (It == Children.end()) {
- T *NewChild = allocatePtr<T>(PersistentArena, ChildToMerge->USR);
- NewChild->merge(std::move(*ChildToMerge));
- Children.push_back(*NewChild);
- } else {
- It->merge(std::move(*ChildToMerge));
- }
- }
-}
-
-template <>
-void reduceChildren<Reference>(
- llvm::simple_ilist<Reference> &Children,
- llvm::simple_ilist<Reference> &&ChildrenToMerge) {
- while (!ChildrenToMerge.empty()) {
- Reference *ChildToMerge = &ChildrenToMerge.front();
- ChildrenToMerge.pop_front();
-
- auto It = llvm::find_if(Children, [&](const Reference &C) {
- return C.USR == ChildToMerge->USR;
- });
- if (It == Children.end()) {
- Reference *NewChild = allocatePtr<Reference>(PersistentArena);
- NewChild->USR = ChildToMerge->USR;
- NewChild->RefType = ChildToMerge->RefType;
- NewChild->merge(std::move(*ChildToMerge));
- Children.push_back(*NewChild);
+ Children.push_back(*ChildToMerge);
} else {
It->merge(std::move(*ChildToMerge));
}
@@ -149,111 +124,14 @@ void reduceChildren<Reference>(
template <typename Container>
static void mergeUnkeyed(Container &Target, Container &&Source) {
- using T = typename Container::value_type;
- while (!Source.empty()) {
- auto &Item = Source.front();
- Source.pop_front();
- if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
- T *NewItem = allocatePtr<T>(PersistentArena, Item);
- Target.push_back(*NewItem);
- }
- }
-}
-
-template <>
-void mergeUnkeyed<OwningVec<CommentInfo>>(OwningVec<CommentInfo> &Target,
- OwningVec<CommentInfo> &&Source) {
while (!Source.empty()) {
auto &Item = Source.front();
Source.pop_front();
- if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
- CommentInfo *NewItem =
- allocatePtr<CommentInfo>(PersistentArena, Item, PersistentArena);
- Target.push_back(*NewItem);
- }
+ if (llvm::none_of(Target, [&](const auto &E) { return E == Item; }))
+ Target.push_back(Item);
}
}
-llvm::Error mergeSingleInfo(doc::OwnedPtr<doc::Info> &Reduced,
- doc::OwnedPtr<doc::Info> &&NewInfo,
- llvm::BumpPtrAllocator &Arena) {
- if (!Reduced) {
- switch (NewInfo->IT) {
- case InfoType::IT_namespace:
- Reduced = allocatePtr<NamespaceInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_record:
- Reduced = allocatePtr<RecordInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_enum:
- Reduced = allocatePtr<EnumInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_function:
- Reduced = allocatePtr<FunctionInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_typedef:
- Reduced = allocatePtr<TypedefInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_concept:
- Reduced = allocatePtr<ConceptInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_variable:
- Reduced = allocatePtr<VarInfo>(Arena, NewInfo->USR);
- break;
- case InfoType::IT_friend:
- Reduced = allocatePtr<FriendInfo>(Arena, NewInfo->USR);
- break;
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "unknown info type");
- }
- }
-
- if (Reduced->IT != NewInfo->IT)
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "info types mismatch");
-
- switch (Reduced->IT) {
- case InfoType::IT_namespace:
- static_cast<NamespaceInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<NamespaceInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_record:
- static_cast<RecordInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<RecordInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_enum:
- static_cast<EnumInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<EnumInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_function:
- static_cast<FunctionInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<FunctionInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_typedef:
- static_cast<TypedefInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<TypedefInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_concept:
- static_cast<ConceptInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<ConceptInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_variable:
- static_cast<VarInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<VarInfo *>(getPtr(NewInfo))));
- break;
- case InfoType::IT_friend:
- static_cast<FriendInfo *>(getPtr(Reduced))
- ->merge(std::move(*static_cast<FriendInfo *>(getPtr(NewInfo))));
- break;
- default:
- return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "unknown info type");
- }
-
- return llvm::Error::success();
-}
-
// Dispatch function.
llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values) {
if (Values.empty() || !Values[0])
@@ -284,20 +162,6 @@ llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values) {
llvm_unreachable("unhandled enumerator");
}
-TemplateSpecializationInfo::TemplateSpecializationInfo(
- const TemplateSpecializationInfo &Other, llvm::BumpPtrAllocator &Arena)
- : SpecializationOf(Other.SpecializationOf) {
- Params = allocateArray(Other.Params, Arena);
-}
-
-TemplateInfo::TemplateInfo(const TemplateInfo &Other,
- llvm::BumpPtrAllocator &Arena) {
- Params = allocateArray(Other.Params, Arena);
- if (Other.Specialization)
- Specialization = TemplateSpecializationInfo(*Other.Specialization, Arena);
- Constraints = allocateArray(Other.Constraints, Arena);
-}
-
bool CommentInfo::operator==(const CommentInfo &Other) const {
auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
SelfClosing, Explicit, AttrKeys, AttrValues, Args);
@@ -333,28 +197,6 @@ bool CommentInfo::operator<(const CommentInfo &Other) const {
return false;
}
-CommentInfo::CommentInfo(const CommentInfo &Other,
- llvm::BumpPtrAllocator &Arena) {
- Kind = Other.Kind;
- Direction = Other.Direction;
- Name = Other.Name;
- ParamName = Other.ParamName;
- CloseName = Other.CloseName;
- SelfClosing = Other.SelfClosing;
- Explicit = Other.Explicit;
- Text = Other.Text;
- AttrKeys = allocateArray(Other.AttrKeys, Arena);
- AttrValues = allocateArray(Other.AttrValues, Arena);
- Args = allocateArray(Other.Args, Arena);
- if (!Other.Children.empty()) {
- CommentInfo *NewArray = Arena.Allocate<CommentInfo>(Other.Children.size());
- for (size_t Idx = 0; Idx < Other.Children.size(); ++Idx) {
- new (NewArray + Idx) CommentInfo(Other.Children[Idx], Arena);
- }
- Children = llvm::ArrayRef<CommentInfo>(NewArray, Other.Children.size());
- }
-}
-
static llvm::SmallString<64>
calculateRelativeFilePath(const InfoType &Type, const StringRef &Path,
const StringRef &Name, const StringRef &CurrentPath) {
@@ -411,8 +253,6 @@ void Reference::merge(Reference &&Other) {
Name = Other.Name;
if (Path.empty())
Path = Other.Path;
- if (QualName.empty())
- QualName = Other.QualName;
if (DocumentationFileName.empty())
DocumentationFileName = Other.DocumentationFileName;
}
@@ -427,31 +267,6 @@ void FriendInfo::merge(FriendInfo &&Other) {
SymbolInfo::merge(std::move(Other));
}
-FriendInfo::FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena)
- : SymbolInfo(Other, Arena) {
- Ref = Other.Ref;
- if (Other.Template)
- Template.emplace(*Other.Template, Arena);
- if (Other.ReturnType)
- ReturnType = Other.ReturnType;
- if (!Other.Params.empty())
- Params = allocateArray(Other.Params, Arena);
- IsClass = Other.IsClass;
-}
-
-Info::Info(const Info &Other, llvm::BumpPtrAllocator &Arena)
- : Path(Other.Path), Name(Other.Name),
- DocumentationFileName(Other.DocumentationFileName), USR(Other.USR),
- ParentUSR(Other.ParentUSR), IT(Other.IT) {
- Namespace = allocateArray(Other.Namespace, Arena);
- if (!Other.Description.empty()) {
- for (const auto &Desc : Other.Description) {
- CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
- Description.push_back(*NewDesc);
- }
- }
-}
-
void Info::mergeBase(Info &&Other) {
assert(mergeable(Other));
if (USR == EmptySID)
@@ -460,8 +275,8 @@ void Info::mergeBase(Info &&Other) {
Name = Other.Name;
if (Path == "")
Path = Other.Path;
- if (Namespace.empty() && !Other.Namespace.empty())
- Namespace = allocateArray(Other.Namespace, PersistentArena);
+ if (Namespace.empty())
+ Namespace = std::move(Other.Namespace);
// Unconditionally extend the description, since each decl may have a comment.
mergeUnkeyed(Description, std::move(Other.Description));
if (ParentUSR == EmptySID)
@@ -474,17 +289,6 @@ bool Info::mergeable(const Info &Other) {
return IT == Other.IT && USR == Other.USR;
}
-SymbolInfo::SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena)
- : Info(Other, Arena), DefLoc(Other.DefLoc), MangledName(Other.MangledName),
- IsStatic(Other.IsStatic) {
- if (!Other.Loc.empty()) {
- for (const auto &L : Other.Loc) {
- Location *NewL = allocatePtr<Location>(Arena, L);
- Loc.push_back(*NewL);
- }
- }
-}
-
void SymbolInfo::merge(SymbolInfo &&Other) {
assert(mergeable(Other));
if (!DefLoc)
@@ -494,8 +298,6 @@ void SymbolInfo::merge(SymbolInfo &&Other) {
mergeBase(std::move(Other));
if (MangledName.empty())
MangledName = std::move(Other.MangledName);
- if (!IsStatic)
- IsStatic = Other.IsStatic;
}
NamespaceInfo::NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path)
@@ -517,76 +319,37 @@ void NamespaceInfo::merge(NamespaceInfo &&Other) {
RecordInfo::RecordInfo(SymbolID USR, StringRef Name, StringRef Path)
: SymbolInfo(InfoType::IT_record, USR, Name, Path) {}
-// FIXME: This constructor is currently unsafe for cross-arena copies of
-// populated records. Because a default copy of ScopeChildren will shallow-copy
-// the intrusive pointers, leading to a use-after-free when the TransientArena
-// is reset. Subsequent patches will address this by deep-copying children
-// individually via reduceChildren.
-RecordInfo::RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena)
- : SymbolInfo(Other, Arena), TagType(Other.TagType),
- IsTypeDef(Other.IsTypeDef) {
- Members = deepCopyArray(Other.Members, Arena);
- Parents = allocateArray(Other.Parents, Arena);
- VirtualParents = allocateArray(Other.VirtualParents, Arena);
- Bases = deepCopyArray(Other.Bases, Arena);
- Friends = deepCopyArray(Other.Friends, Arena);
-}
-
-MemberTypeInfo::MemberTypeInfo(const MemberTypeInfo &Other,
- llvm::BumpPtrAllocator &Arena)
- : FieldTypeInfo(Other), Access(Other.Access), IsStatic(Other.IsStatic) {
- if (!Other.Description.empty()) {
- for (const auto &Desc : Other.Description) {
- CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
- Description.push_back(*NewDesc);
- }
- }
-}
-
void RecordInfo::merge(RecordInfo &&Other) {
assert(mergeable(Other));
if (!llvm::to_underlying(TagType))
TagType = Other.TagType;
IsTypeDef = IsTypeDef || Other.IsTypeDef;
- if (Members.empty() && !Other.Members.empty())
- Members = deepCopyArray(Other.Members, PersistentArena);
- if (Bases.empty() && !Other.Bases.empty())
- Bases = deepCopyArray(Other.Bases, PersistentArena);
- if (Parents.empty() && !Other.Parents.empty())
- Parents = allocateArray(Other.Parents, PersistentArena);
- if (VirtualParents.empty() && !Other.VirtualParents.empty())
- VirtualParents = allocateArray(Other.VirtualParents, PersistentArena);
- if (Friends.empty() && !Other.Friends.empty())
- Friends = deepCopyArray(Other.Friends, PersistentArena);
+ if (Members.empty())
+ Members = std::move(Other.Members);
+ if (Bases.empty())
+ Bases = std::move(Other.Bases);
+ if (Parents.empty())
+ Parents = std::move(Other.Parents);
+ if (VirtualParents.empty())
+ VirtualParents = std::move(Other.VirtualParents);
+ if (Friends.empty())
+ Friends = std::move(Other.Friends);
// Reduce children if necessary.
reduceChildren(Children.Records, std::move(Other.Children.Records));
reduceChildren(Children.Functions, std::move(Other.Children.Functions));
reduceChildren(Children.Enums, std::move(Other.Children.Enums));
reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs));
SymbolInfo::merge(std::move(Other));
- if (!Template && Other.Template)
- Template = TemplateInfo(*Other.Template, PersistentArena);
-}
-
-EnumValueInfo::EnumValueInfo(const EnumValueInfo &Other,
- llvm::BumpPtrAllocator &Arena)
- : Name(Other.Name), Value(Other.Value), ValueExpr(Other.ValueExpr) {
- if (!Other.Description.empty()) {
- for (const auto &Desc : Other.Description) {
- CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
- Description.push_back(*NewDesc);
- }
- }
+ if (!Template)
+ Template = Other.Template;
}
void EnumInfo::merge(EnumInfo &&Other) {
assert(mergeable(Other));
if (!Scoped)
Scoped = Other.Scoped;
- if (!BaseType && Other.BaseType)
- BaseType = std::move(Other.BaseType);
- if (Members.empty() && !Other.Members.empty())
- Members = deepCopyArray(Other.Members, PersistentArena);
+ if (Members.empty())
+ Members = std::move(Other.Members);
SymbolInfo::merge(std::move(Other));
}
@@ -600,11 +363,11 @@ void FunctionInfo::merge(FunctionInfo &&Other) {
ReturnType = std::move(Other.ReturnType);
if (Parent.USR == EmptySID && Parent.Name == "")
Parent = std::move(Other.Parent);
- if (Params.empty() && !Other.Params.empty())
- Params = allocateArray(Other.Params, PersistentArena);
+ if (Params.empty())
+ Params = std::move(Other.Params);
SymbolInfo::merge(std::move(Other));
- if (!Template && Other.Template)
- Template = TemplateInfo(*Other.Template, PersistentArena);
+ if (!Template)
+ Template = Other.Template;
}
void TypedefInfo::merge(TypedefInfo &&Other) {
@@ -613,8 +376,8 @@ void TypedefInfo::merge(TypedefInfo &&Other) {
IsUsing = Other.IsUsing;
if (Underlying.Type.Name == "")
Underlying = Other.Underlying;
- if (!Template && Other.Template)
- Template = TemplateInfo(*Other.Template, PersistentArena);
+ if (!Template)
+ Template = Other.Template;
SymbolInfo::merge(std::move(Other));
}
@@ -624,11 +387,10 @@ void ConceptInfo::merge(ConceptInfo &&Other) {
IsType = Other.IsType;
if (ConstraintExpression.empty())
ConstraintExpression = std::move(Other.ConstraintExpression);
- if (Template.Constraints.empty() && !Other.Template.Constraints.empty())
- Template.Constraints =
- allocateArray(Other.Template.Constraints, PersistentArena);
- if (Template.Params.empty() && !Other.Template.Params.empty())
- Template.Params = allocateArray(Other.Template.Params, PersistentArena);
+ if (Template.Constraints.empty())
+ Template.Constraints = std::move(Other.Template.Constraints);
+ if (Template.Params.empty())
+ Template.Params = std::move(Other.Template.Params);
SymbolInfo::merge(std::move(Other));
}
@@ -643,11 +405,6 @@ void VarInfo::merge(VarInfo &&Other) {
BaseRecordInfo::BaseRecordInfo() : RecordInfo() {}
-BaseRecordInfo::BaseRecordInfo(const BaseRecordInfo &Other,
- llvm::BumpPtrAllocator &Arena)
- : RecordInfo(Other, Arena), Access(Other.Access),
- IsVirtual(Other.IsVirtual), IsParent(Other.IsParent) {}
-
BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path,
bool IsVirtual, AccessSpecifier Access,
bool IsParent)
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 5f404463b012e..f73ab751b7ba3 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -52,7 +52,6 @@ class ConcurrentStringPool {
ConcurrentStringPool &getGlobalStringPool();
extern thread_local llvm::BumpPtrAllocator TransientArena;
-extern thread_local llvm::BumpPtrAllocator PersistentArena;
inline StringRef internString(const Twine &T) {
if (T.isTriviallyEmpty())
@@ -92,18 +91,6 @@ llvm::ArrayRef<T> allocateArray(llvm::ArrayRef<T> V,
return llvm::ArrayRef<T>(Allocated, V.size());
}
-template <typename T>
-llvm::ArrayRef<T> deepCopyArray(llvm::ArrayRef<T> V,
- llvm::BumpPtrAllocator &Alloc) {
- if (V.empty())
- return llvm::ArrayRef<T>();
- T *Allocated = (T *)Alloc.Allocate<T>(V.size());
- for (size_t Idx = 0; Idx < V.size(); ++Idx) {
- new (Allocated + Idx) T(V[Idx], Alloc);
- }
- return llvm::ArrayRef<T>(Allocated, V.size());
-}
-
// An abstraction for owned pointers. Initially mapped to OwnedPtr,
// to be eventually transitioned to bare pointers in an arena.
template <typename T> using OwnedPtr = T *;
@@ -193,7 +180,6 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
CommentInfo() = default;
CommentInfo(const CommentInfo &Other) = default;
CommentInfo &operator=(const CommentInfo &Other) = default;
- CommentInfo(const CommentInfo &Other, llvm::BumpPtrAllocator &Arena);
CommentInfo(CommentInfo &&Other) = default;
CommentInfo &operator=(CommentInfo &&Other) = default;
@@ -219,11 +205,11 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
llvm::ArrayRef<CommentInfo>
Children; // List of child comments for this CommentInfo.
- StringRef Direction = {}; // Parameter direction (for (T)ParamCommand).
- StringRef Name = {}; // Name of the comment (for Verbatim and HTML).
- StringRef ParamName = {}; // Parameter name (for (T)ParamCommand).
- StringRef CloseName = {}; // Closing tag name (for VerbatimBlock).
- StringRef Text = {}; // Text of the comment.
+ StringRef Direction; // Parameter direction (for (T)ParamCommand).
+ StringRef Name; // Name of the comment (for Verbatim and HTML).
+ StringRef ParamName; // Parameter name (for (T)ParamCommand).
+ StringRef CloseName; // Closing tag name (for VerbatimBlock).
+ StringRef Text; // Text of the comment.
llvm::ArrayRef<StringRef> AttrKeys; // List of attribute keys (for HTML).
llvm::ArrayRef<StringRef>
AttrValues; // List of attribute values for each key (for HTML).
@@ -285,17 +271,17 @@ struct Reference : public llvm::ilist_node<Reference> {
// Name of type (possibly unresolved). Not including namespaces or template
// parameters (so for a std::vector<int> this would be "vector"). See also
// QualName.
- StringRef Name = {};
+ StringRef Name;
// Full qualified name of this type, including namespaces and template
// parameter (for example this could be "std::vector<int>"). Contrast to
// Name.
- StringRef QualName = {};
+ StringRef QualName;
// Path of directory where the clang-doc generated file will be saved
// (possibly unresolved)
- StringRef Path = {};
- StringRef DocumentationFileName = {};
+ StringRef Path;
+ StringRef DocumentationFileName;
};
// A Context is a reference that holds a relative path from a certain Info's
@@ -305,7 +291,7 @@ struct Context : public Reference {
StringRef Path, StringRef DocumentationFileName)
: Reference(USR, Name, IT, QualName, Path, DocumentationFileName) {}
explicit Context(const Info &I);
- StringRef RelativePath = {};
+ StringRef RelativePath;
};
// Holds the childre...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/191668
More information about the cfe-commits
mailing list