[clang] [analyzer] Assert isImplicitObjectMemberFunction in SValBuilder::getCXXThis (PR #220114)
Benedek Kaibas via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 17 05:31:40 PDT 2026
https://github.com/benedekaibas updated https://github.com/llvm/llvm-project/pull/220114
>From cd800a911d402fafe1f32e4ff2709d5061732e08 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Sat, 29 Aug 2026 22:41:18 +0200
Subject: [PATCH 1/9] [analyzer] Resolve lambda captures for explicit object
parameters
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 26 +++++++++--
.../test/Analysis/explicit-lambda-capture.cpp | 43 +++++++++++++++++++
2 files changed, 65 insertions(+), 4 deletions(-)
create mode 100644 clang/test/Analysis/explicit-lambda-capture.cpp
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index e6349eb4eba2ae..01e05924a25378 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3040,12 +3040,30 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
// Sema follows a sequence of complex rules to determine whether the
// variable should be captured.
if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
- Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
- SVal CXXThisVal = state->getSVal(CXXThis);
- return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
+ if (MD->isImplicitObjectMemberFunction()) {
+ Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
+ SVal CXXThisVal = state->getSVal(CXXThis);
+ return std::make_pair(state->getLValue(FD, CXXThisVal),
+ FD->getType());
+ }
+ const ParmVarDecl *PVD = MD->getParamDecl(0);
+ if (const Expr *CallSite = SF->getCallSite()) {
+ unsigned Idx = PVD->getFunctionScopeIndex();
+ const ParamVarRegion *PVR =
+ state->getStateManager().getRegionManager().getParamVarRegion(
+ CallSite, Idx, SF);
+ const Expr *SelfArgExpr = cast<CallExpr>(CallSite)->getArg(0);
+ state =
+ state->bindLoc(loc::MemRegionVal(PVR),
+ state->getSVal(SelfArgExpr, SF->getParent()), SF);
+ SVal ParamSVal = state->getSVal(loc::MemRegionVal(PVR));
+ if (!PVD->getType()->isReferenceType())
+ return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)),
+ FD->getType());
+ return std::make_pair(state->getLValue(FD, ParamSVal), FD->getType());
+ }
}
}
-
return std::nullopt;
};
diff --git a/clang/test/Analysis/explicit-lambda-capture.cpp b/clang/test/Analysis/explicit-lambda-capture.cpp
new file mode 100644
index 00000000000000..2d98b80ce9637f
--- /dev/null
+++ b/clang/test/Analysis/explicit-lambda-capture.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -analyze -std=c++23 -analyzer-checker=core.DivideZero -verify %s
+
+int implicit_capture_by_value() {
+ int d = 0;
+ auto lam = [d]() { return 1 / d; }; // expected-warning {{Division by zero}}
+ return lam();
+}
+
+int explicit_rvalue_self_capture_by_reference() {
+ int d = 0;
+ auto lam = [&d](this auto &&self) { return 1 / d; }; // expected-warning {{Division by zero}}
+ return lam();
+}
+
+int gh218708_explicit_rvalue_self() {
+ int d = 0;
+ auto lam = [d](this auto &&self) { return 1 / d; }; // expected-warning {{Division by zero}}
+ return lam();
+}
+
+int gh218708_explicit_lvalue_self() {
+ int d = 0;
+ auto lam = [d](this auto &self) { return 1 / d; }; // expected-warning {{Division by zero}}
+ return lam();
+}
+
+int gh218708_explicit_by_value_self() {
+ int d = 0;
+ auto lam = [d](this auto self) { return 1 / d; }; // expected-warning {{Division by zero}}
+ return lam();
+}
+
+int explicit_rvalue_no_error() {
+ int d = 5;
+ auto lam = [d](this auto &&self) { return 1 / d; }; // 'd' is non-zero so there is no division by zero error.
+ return lam();
+}
+
+int explicit_by_value_no_error() {
+ int d = 9;
+ auto lam = [d](this auto self) { return 1 / d; }; // 'd' is non-zero so there is no division by zero error.
+ return lam();
+}
>From 14f335aaecfcfe15de5aa0550c210b97e20a5283 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Sat, 29 Aug 2026 22:58:50 +0200
Subject: [PATCH 2/9] Fix unconditional compute for the reference type
construction.
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 01e05924a25378..0ab2d22b87fe26 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3053,14 +3053,15 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
state->getStateManager().getRegionManager().getParamVarRegion(
CallSite, Idx, SF);
const Expr *SelfArgExpr = cast<CallExpr>(CallSite)->getArg(0);
- state =
- state->bindLoc(loc::MemRegionVal(PVR),
- state->getSVal(SelfArgExpr, SF->getParent()), SF);
- SVal ParamSVal = state->getSVal(loc::MemRegionVal(PVR));
- if (!PVD->getType()->isReferenceType())
- return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)),
+ if (PVD->getType()->isReferenceType()) {
+ state = state->bindLoc(loc::MemRegionVal(PVR),
+ state->getSVal(SelfArgExpr, SF->getParent()),
+ SF);
+ SVal ParamSVal = state->getSVal(loc::MemRegionVal(PVR));
+ return std::make_pair(state->getLValue(FD, ParamSVal),
FD->getType());
- return std::make_pair(state->getLValue(FD, ParamSVal), FD->getType());
+ }
+ return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)), FD->getType());
}
}
}
>From 19674e6cff8045269ef8655cd4e16816127af6f4 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Sat, 29 Aug 2026 23:05:25 +0200
Subject: [PATCH 3/9] Fix formatting issue
---
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0ab2d22b87fe26..c503d686fb407d 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3061,7 +3061,8 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
return std::make_pair(state->getLValue(FD, ParamSVal),
FD->getType());
}
- return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)), FD->getType());
+ return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)),
+ FD->getType());
}
}
}
>From 57ec566d0cf17f95ae58630740d8c90be7d2877b Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Mon, 31 Aug 2026 11:43:52 +0200
Subject: [PATCH 4/9] Correct comments and RUN line.
---
clang/test/Analysis/explicit-lambda-capture.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/Analysis/explicit-lambda-capture.cpp b/clang/test/Analysis/explicit-lambda-capture.cpp
index 2d98b80ce9637f..89d249a63da43e 100644
--- a/clang/test/Analysis/explicit-lambda-capture.cpp
+++ b/clang/test/Analysis/explicit-lambda-capture.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -std=c++23 -analyzer-checker=core.DivideZero -verify %s
+// RUN: %clang_analyze_cc1 -std=c++23 -analyzer-checker=core -verify %s
int implicit_capture_by_value() {
int d = 0;
@@ -32,12 +32,12 @@ int gh218708_explicit_by_value_self() {
int explicit_rvalue_no_error() {
int d = 5;
- auto lam = [d](this auto &&self) { return 1 / d; }; // 'd' is non-zero so there is no division by zero error.
+ auto lam = [d](this auto &&self) { return 1 / d; }; // no-warning
return lam();
}
int explicit_by_value_no_error() {
int d = 9;
- auto lam = [d](this auto self) { return 1 / d; }; // 'd' is non-zero so there is no division by zero error.
+ auto lam = [d](this auto self) { return 1 / d; }; // no-warning
return lam();
}
>From 9c54a9ba6ebd4f50e021855294c40465bae60de2 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Mon, 31 Aug 2026 12:35:51 +0200
Subject: [PATCH 5/9] Created resolveAsLambdaCapturedVar function and included
the MRMgr direct reference.
---
.../Core/PathSensitive/ExprEngine.h | 4 +
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 91 +++++++++----------
2 files changed, 49 insertions(+), 46 deletions(-)
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 68d4362aca9417..19ceec5cf2df60 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -677,6 +677,10 @@ class ExprEngine {
static std::pair<const ProgramPointTag *, const ProgramPointTag *>
getEagerlyAssumeBifurcationTags();
+ std::optional<std::pair<SVal, QualType>>
+ resolveAsLambdaCapturedVar(const Expr *Ex, const ValueDecl *VD,
+ ExplodedNode *Pred);
+
ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
const StackFrame *SF, QualType T,
QualType ExTy, const CastExpr *CastE,
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index c503d686fb407d..1f047c82c32e99 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3018,63 +3018,62 @@ void ExprEngine::processSwitch(const SwitchStmt *Switch, ExplodedNode *Pred,
// Transfer functions: Loads and stores.
//===----------------------------------------------------------------------===//
-void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+std::optional<std::pair<SVal, QualType>>
+ExprEngine::resolveAsLambdaCapturedVar(const Expr *Ex, const ValueDecl *VD,
+ ExplodedNode *Pred) {
ProgramStateRef state = Pred->getState();
const StackFrame *SF = Pred->getStackFrame();
- auto resolveAsLambdaCapturedVar =
- [&](const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {
- const auto *MD = dyn_cast<CXXMethodDecl>(SF->getDecl());
- const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
- if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
- DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
- MD->getParent()->isLambda()) {
- // Lookup the field of the lambda.
- const CXXRecordDecl *CXXRec = MD->getParent();
- llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
- FieldDecl *LambdaThisCaptureField;
- CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
-
- // Sema follows a sequence of complex rules to determine whether the
- // variable should be captured.
- if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
- if (MD->isImplicitObjectMemberFunction()) {
- Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
- SVal CXXThisVal = state->getSVal(CXXThis);
- return std::make_pair(state->getLValue(FD, CXXThisVal),
- FD->getType());
- }
- const ParmVarDecl *PVD = MD->getParamDecl(0);
- if (const Expr *CallSite = SF->getCallSite()) {
- unsigned Idx = PVD->getFunctionScopeIndex();
- const ParamVarRegion *PVR =
- state->getStateManager().getRegionManager().getParamVarRegion(
- CallSite, Idx, SF);
- const Expr *SelfArgExpr = cast<CallExpr>(CallSite)->getArg(0);
- if (PVD->getType()->isReferenceType()) {
- state = state->bindLoc(loc::MemRegionVal(PVR),
- state->getSVal(SelfArgExpr, SF->getParent()),
- SF);
- SVal ParamSVal = state->getSVal(loc::MemRegionVal(PVR));
- return std::make_pair(state->getLValue(FD, ParamSVal),
- FD->getType());
- }
- return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)),
- FD->getType());
+ const auto *MD = dyn_cast<CXXMethodDecl>(SF->getDecl());
+ const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
+ if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
+ DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
+ MD->getParent()->isLambda()) {
+ // Lookup the field of the lambda.
+ const CXXRecordDecl *CXXRec = MD->getParent();
+ llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
+ FieldDecl *LambdaThisCaptureField;
+ CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
+
+ // Sema follows a sequence of complex rules to determine whether the
+ // variable should be captured.
+ if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
+ if (MD->isImplicitObjectMemberFunction()) {
+ Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
+ SVal CXXThisVal = state->getSVal(CXXThis);
+ return {{state->getLValue(FD, CXXThisVal), FD->getType()}};
+ }
+ const ParmVarDecl *PVD = MD->getParamDecl(0);
+ if (const Expr *CallSite = SF->getCallSite()) {
+ const ParamVarRegion *PVR =
+ MRMgr.getParamVarRegion(CallSite, /*Index=*/0, SF);
+ const Expr *SelfArgExpr = cast<CallExpr>(CallSite)->getArg(0);
+ if (PVD->getType()->isReferenceType()) {
+ state =
+ state->bindLoc(loc::MemRegionVal(PVR),
+ state->getSVal(SelfArgExpr, SF->getParent()), SF);
+ SVal ParamSVal = state->getSVal(loc::MemRegionVal(PVR));
+ return {{state->getLValue(FD, ParamSVal), FD->getType()}};
}
+ return {{state->getLValue(FD, loc::MemRegionVal(PVR)), FD->getType()}};
}
}
- return std::nullopt;
- };
+ }
+ return std::nullopt;
+}
+
+void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ProgramStateRef state = Pred->getState();
+ const StackFrame *SF = Pred->getStackFrame();
if (const auto *VD = dyn_cast<VarDecl>(D)) {
// C permits "extern void v", and if you cast the address to a valid type,
// you can even do things with it. We simply pretend
assert(Ex->isGLValue() || VD->getType()->isVoidType());
std::optional<std::pair<SVal, QualType>> VInfo =
- resolveAsLambdaCapturedVar(VD);
+ resolveAsLambdaCapturedVar(Ex, VD, Pred);
if (!VInfo)
VInfo = std::make_pair(state->getLValue(VD, SF), VD->getType());
@@ -3116,7 +3115,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
if (const auto *BD = dyn_cast<BindingDecl>(D)) {
// Handle structured bindings captured by lambda.
if (std::optional<std::pair<SVal, QualType>> VInfo =
- resolveAsLambdaCapturedVar(BD)) {
+ resolveAsLambdaCapturedVar(Ex, BD, Pred)) {
auto [V, T] = VInfo.value();
if (T->isReferenceType()) {
>From fbb50ddfec1f359fa09da7e85fcc78e2e4c8aabc Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Mon, 31 Aug 2026 22:33:31 +0200
Subject: [PATCH 6/9] Add more test cases.
---
.../test/Analysis/explicit-lambda-capture.cpp | 37 ++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/clang/test/Analysis/explicit-lambda-capture.cpp b/clang/test/Analysis/explicit-lambda-capture.cpp
index 89d249a63da43e..5d5100f8eb723b 100644
--- a/clang/test/Analysis/explicit-lambda-capture.cpp
+++ b/clang/test/Analysis/explicit-lambda-capture.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_analyze_cc1 -std=c++23 -analyzer-checker=core -verify %s
+// RUN: %clang_analyze_cc1 -std=c++23 -analyzer-checker=core,cplusplus.Move -verify %s
+
+#include "Inputs/system-header-simulator-cxx.h"
int implicit_capture_by_value() {
int d = 0;
@@ -41,3 +43,36 @@ int explicit_by_value_no_error() {
auto lam = [d](this auto self) { return 1 / d; }; // no-warning
return lam();
}
+
+auto by_val() {
+ std::vector<int> v;
+ auto lam = [v](this auto self) {
+ auto res = std::move(v);
+ return res;
+ };
+
+ lam();
+ lam();
+}
+
+auto by_lval() {
+ std::vector<int> v;
+ auto lam = [v](this auto &self) {
+ auto res = std::move(v); // expected-warning {{Moved-from object '' of type 'std::vector' is moved}}
+ return res;
+ };
+
+ lam();
+ lam();
+}
+
+auto by_rval() {
+ std::vector<int> v;
+ auto lam = [v](this auto &&self) {
+ auto res = std::move(v); // expected-warning {{Moved-from object '' of type 'std::vector' is moved}}
+ return res;
+ };
+
+ std::move(lam)();
+ std::move(lam)();
+}
>From efda1198e71a09e79bc514cac5d381209a2d217c Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Tue, 1 Sep 2026 00:19:30 +0200
Subject: [PATCH 7/9] [analyzer] Assert isImplicitObjectMemberFunction in
SValBuilder::getCXXThis
---
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 55669c1bef5d14..1c503be602b9fa 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -311,6 +311,7 @@ SValBuilder::getCastedMemRegionVal(const MemRegion *R, QualType Ty) {
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
const StackFrame *SF) {
+ assert(D->isImplicitObjectMemberFunction() && "D must be an implicit object member function");
return loc::MemRegionVal(
getRegionManager().getCXXThisRegion(D->getThisType(), SF));
}
>From 0ec03f49fb1d014995933a3a7e0e3e50908a3ff1 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Tue, 1 Sep 2026 00:28:17 +0200
Subject: [PATCH 8/9] Run clang-format.
---
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 1c503be602b9fa..1f689cca735cea 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -311,7 +311,8 @@ SValBuilder::getCastedMemRegionVal(const MemRegion *R, QualType Ty) {
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
const StackFrame *SF) {
- assert(D->isImplicitObjectMemberFunction() && "D must be an implicit object member function");
+ assert(D->isImplicitObjectMemberFunction() &&
+ "D must be an implicit object member function");
return loc::MemRegionVal(
getRegionManager().getCXXThisRegion(D->getThisType(), SF));
}
>From f28c264da2c3e83c5c9edd02b39aa3b08c6e8cf0 Mon Sep 17 00:00:00 2001
From: benedekaibas <kaibas01 at allegheny.edu>
Date: Wed, 2 Sep 2026 15:33:39 +0200
Subject: [PATCH 9/9] Add guard for MD to check if it is an implicit object
member function.
---
clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
index be31f5c94c4af3..84320909999d26 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
@@ -44,6 +44,9 @@ void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {
return;
if (!MD->isCopyAssignmentOperator() && !MD->isMoveAssignmentOperator())
return;
+ if (!MD->isImplicitObjectMemberFunction())
+ return;
+
auto &State = C.getState();
auto &SVB = C.getSValBuilder();
auto ThisVal = State->getSVal(SVB.getCXXThis(MD, SF));
More information about the cfe-commits
mailing list