From 326b564fd2de0b2b2c37d4cb76f46030c4e979a2 Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Mon, 1 Sep 2025 19:37:16 +0800 Subject: [PATCH 1/2] [cfg] fixed the bug where CFG construction was incorrect in the presence of SafeStmt and SafeExpr, which could lead to false positive in borrow checking --- clang/lib/Analysis/CFG.cpp | 8 ++ .../borrow_in_safe_expr_and_stmt.cbs | 86 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 clang/test/BSC/Positive/Ownership/borrow_check_rules/borrow_in_safe_expr_and_stmt/borrow_in_safe_expr_and_stmt.cbs diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 2d48e8a945af..b52d88834492 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2150,6 +2150,14 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, default: return VisitStmt(S, asc); +#if ENABLE_BSC + case Stmt::SafeStmtClass: + return Visit(cast(S)->getSubStmt(), asc, ExternallyDestructed); + + case Stmt::SafeExprClass: + return Visit(cast(S)->getSubExpr(), asc, ExternallyDestructed); +#endif + case Stmt::ImplicitValueInitExprClass: if (BuildOpts.OmitImplicitValueInitializers) return Block; diff --git a/clang/test/BSC/Positive/Ownership/borrow_check_rules/borrow_in_safe_expr_and_stmt/borrow_in_safe_expr_and_stmt.cbs b/clang/test/BSC/Positive/Ownership/borrow_check_rules/borrow_in_safe_expr_and_stmt/borrow_in_safe_expr_and_stmt.cbs new file mode 100644 index 000000000000..541bddd883de --- /dev/null +++ b/clang/test/BSC/Positive/Ownership/borrow_check_rules/borrow_in_safe_expr_and_stmt/borrow_in_safe_expr_and_stmt.cbs @@ -0,0 +1,86 @@ +// RUN: %clang %s -o %test.output +// RUN: %test.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output +// expected-no-diagnostics + +safe void use(int *borrow p) { + *p = 5; +} + +void test1(int a, int b, char c) { + safe switch (a) { + case 5: { + int *borrow pb = &mut b; + use(pb); + break; + } + default: + c += 1; + } +} + +void test2(int a, int b, char c) { + safe switch (a) { + case 0: + a += 1; + break; + case 1: + a += 2; + case 2: + case 3: + break; + case 4: { + c += 1; + break; + } + case 5: { + int *borrow pb = &mut b; + use(pb); + break; + } + case 6: + unsafe { + safe { + unsafe { + safe switch (c) { + case 0: + a+=1; + break; + case 1: + a += 2; + case 2: + case 3: + break; + case 4: { + c += 1; + break; + } + case 5: { + int *borrow pb = &mut b; + use(pb); + break; + } + default: + c += 1; + } + break; + } + } + } + case 7: + unsafe { + a++; + break; + } + default: + c += 1; + } +} + +int main(void) { + test1(5, 2, '3'); + test2(1, 2, '3'); + return 0; +} -- Gitee From a34a939445536d0fecb4cd6baa3ea21ebdb3724a Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Tue, 2 Sep 2025 09:25:16 +0800 Subject: [PATCH 2/2] [borrowck] fixed coredump caused by RegionName not binded to RegionVariable in single-assignment function bodies --- .../Analysis/Analyses/BSC/BSCBorrowChecker.h | 2 +- clang/lib/Analysis/BSC/BSCBorrowChecker.cpp | 4 ++++ .../reborrow_raw_pointers.cbs | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 clang/test/BSC/Positive/Ownership/borrow_check_rules/reborrow_raw_pointers/reborrow_raw_pointers.cbs diff --git a/clang/include/clang/Analysis/Analyses/BSC/BSCBorrowChecker.h b/clang/include/clang/Analysis/Analyses/BSC/BSCBorrowChecker.h index 7fbca6ef0317..dada516dc83a 100644 --- a/clang/include/clang/Analysis/Analyses/BSC/BSCBorrowChecker.h +++ b/clang/include/clang/Analysis/Analyses/BSC/BSCBorrowChecker.h @@ -939,7 +939,7 @@ private: std::map>> actionMap; void PopulateInference(Liveness &liveness); - RegionVariable getRegionVariable(RegionName RV); + RegionVariable getRegionVariable(RegionName RN); void EnsureBorrowSource(Point SuccPoint, RegionName BorrowRegionName, const std::unique_ptr &SourcePath); void RelateRegions(Point SuccPoint, RegionName Sub, RegionName Sup); diff --git a/clang/lib/Analysis/BSC/BSCBorrowChecker.cpp b/clang/lib/Analysis/BSC/BSCBorrowChecker.cpp index 28c6de15182b..4d58e313b5ca 100644 --- a/clang/lib/Analysis/BSC/BSCBorrowChecker.cpp +++ b/clang/lib/Analysis/BSC/BSCBorrowChecker.cpp @@ -1557,6 +1557,8 @@ RegionName RegionCheck::getRegionName(Decl *D) { << RN.print() << '\n'; #endif declToRegionNameMap[D] = RN; + // Ensure that the region variable corresponding to RN exists. + (void)getRegionVariable(RN); return RN; } @@ -1569,6 +1571,8 @@ RegionName RegionCheck::getRegionName(Stmt *S) { << '\n'; #endif stmtToRegionNameMap[S] = RN; + // Ensure that the region variable corresponding to RN exists. + (void)getRegionVariable(RN); return RN; } diff --git a/clang/test/BSC/Positive/Ownership/borrow_check_rules/reborrow_raw_pointers/reborrow_raw_pointers.cbs b/clang/test/BSC/Positive/Ownership/borrow_check_rules/reborrow_raw_pointers/reborrow_raw_pointers.cbs new file mode 100644 index 000000000000..a046c16d0782 --- /dev/null +++ b/clang/test/BSC/Positive/Ownership/borrow_check_rules/reborrow_raw_pointers/reborrow_raw_pointers.cbs @@ -0,0 +1,24 @@ +// RUN: %clang %s -o %test.output +// RUN: %test.output +// RUN: %clang -rewrite-bsc %s -o %t-rw.c +// RUN: %clang %t-rw.c -o %t-rw.output +// RUN: %t-rw.output +// expected-no-diagnostics + +void call1(int *borrow p, int *raw) { + p = &mut *raw; +} + +void call2(const int *borrow q, int x) { + q = &const x; +} + +int main() { + int a = 1, b = 2; + int *raw = &a; + int *borrow p = &mut a; + const int *borrow q = &const b; + call1(p, raw); + call2(q, 2); + return 0; +} \ No newline at end of file -- Gitee