From 0bc7d7c6271afa7db1534e7c8d87bf697816bc7c Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Wed, 27 Aug 2025 10:44:10 +0800 Subject: [PATCH 1/3] [borrow] fix the bug of unexpected error diagnostic message triggered by reborrow in a generic function --- clang/lib/Sema/SemaExpr.cpp | 4 +-- .../reborrow_in_generic.cbs | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 clang/test/BSC/Positive/Ownership/reborrow_in_generic/reborrow_in_generic.cbs diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ddc38107a9ea..37def7ff1d96 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14923,7 +14923,7 @@ QualType Sema::GetBorrowAddressOperandQualType(QualType resultType, if (Opc == UO_AddrMut && IsAddrBorrowDerefOp(Input)) { Opc = UO_AddrMutDeref; } else { - if (InputExpr->getType().hasBorrow()) + if (Opc == UO_AddrMut && InputExpr->getType().hasBorrow()) Diag(OpLoc, diag::err_borrow_on_borrow) << "'&mut'" << InputExpr->getSourceRange(); if (InputExpr->getType().isConstQualified()) @@ -14956,7 +14956,7 @@ QualType Sema::GetBorrowAddressOperandQualType(QualType resultType, if (Opc == UO_AddrConst && IsAddrBorrowDerefOp(Input)) { Opc = UO_AddrConstDeref; } else { - if (InputExpr->getType().hasBorrow()) + if (Opc == UO_AddrConst && InputExpr->getType().hasBorrow()) Diag(OpLoc, diag::err_borrow_on_borrow) << "'&const'" << InputExpr->getSourceRange(); } diff --git a/clang/test/BSC/Positive/Ownership/reborrow_in_generic/reborrow_in_generic.cbs b/clang/test/BSC/Positive/Ownership/reborrow_in_generic/reborrow_in_generic.cbs new file mode 100644 index 000000000000..8174168babf8 --- /dev/null +++ b/clang/test/BSC/Positive/Ownership/reborrow_in_generic/reborrow_in_generic.cbs @@ -0,0 +1,31 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +void use(int *borrow p) { + *p = 2; +} + +void use_immut(const int *borrow p) { + int x = *p; +} + +void test1() { + int a = 1; + int *borrow p = &mut a; + int *borrow q = &mut *p; + use(q); +} + +void test2() { + int a = 1; + int *borrow p = &mut a; + const int *borrow q = &const *p; + use_immut(q); +} + +int main() { + test1(); + test2(); + return 0; +} -- Gitee From 5d5aa295f96459b1ab61f382dba167a58503146c Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Wed, 27 Aug 2025 10:54:39 +0800 Subject: [PATCH 2/3] [typo] fix a typo in the diagnostic message and adapt the test cases --- .../clang/Basic/BSC/DiagnosticBSCSemaKinds.td | 2 +- .../borrow_on_borrow/borrow_on_borrow.cbs | 44 +++++++++---------- .../Ownership/Borrow/borrow_op/borrow_op.cbs | 8 ++-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td b/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td index 3febc8c33974..2fa516bc0c1d 100644 --- a/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td +++ b/clang/include/clang/Basic/BSC/DiagnosticBSCSemaKinds.td @@ -65,7 +65,7 @@ def err_owned_temporary_memLeak : Error< "memory leak because temporary variable '%0' is owned or indirect owned type, please fix it">; def err_funcPtr_incompatible : Error< "incompatible borrow function pointer types, cannot cast %0 to %1">; -def err_borrow_on_borrow : Error<"%0 on a 'borrow' quialified type is not allowed">; +def err_borrow_on_borrow : Error<"%0 on a 'borrow' qualified type is not allowed">; def err_mut_expr_unmodifiable : Error<"the expression after '&mut' must be modifiable">; def err_mut_expr_func : Error<"'&mut' for function pointer is not allowed">; def err_safe_mut : Error<"global or static variables are not allowed to be mutably borrowed within the safe zone">; diff --git a/clang/test/BSC/Negative/Ownership/Borrow/borrow_on_borrow/borrow_on_borrow.cbs b/clang/test/BSC/Negative/Ownership/Borrow/borrow_on_borrow/borrow_on_borrow.cbs index aebd4ad4c86b..00ef6f9238b1 100644 --- a/clang/test/BSC/Negative/Ownership/Borrow/borrow_on_borrow/borrow_on_borrow.cbs +++ b/clang/test/BSC/Negative/Ownership/Borrow/borrow_on_borrow/borrow_on_borrow.cbs @@ -9,48 +9,48 @@ void test() { int b = 1; int *borrow p1 = &mut a; // legal const int *borrow p2 = &const b; // legal - int *borrow * borrow b1 = &mut p1; // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} + int *borrow * borrow b1 = &mut p1; // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} const int *borrow const * borrow b2 = &const p2; /* expected-error {{incompatible borrow types, cannot cast 'const int *borrow *borrow' to 'const int *const borrow *borrow'}} - expected-error {{'&const' on a 'borrow' quialified type is not allowed}} */ + expected-error {{'&const' on a 'borrow' qualified type is not allowed}} */ int *borrow const * borrow b3 = &const p1; /* expected-error {{incompatible borrow types, cannot cast 'const int *borrow *borrow' to 'int *const borrow *borrow'}} - expected-error {{'&const' on a 'borrow' quialified type is not allowed}} */ - const int * borrow * borrow b4 = &mut p2; // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} - int *borrow *borrow p3 = &mut (&mut a); // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} - const int *borrow *borrow p4 = &mut (&const b); // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} + expected-error {{'&const' on a 'borrow' qualified type is not allowed}} */ + const int * borrow * borrow b4 = &mut p2; // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} + int *borrow *borrow p3 = &mut (&mut a); // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} + const int *borrow *borrow p4 = &mut (&const b); // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} const int *borrow const * borrow p5 = &const (&const b); /* expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} - expected-error {{'&const' on a 'borrow' quialified type is not allowed}} */ + expected-error {{'&const' on a 'borrow' qualified type is not allowed}} */ int *borrow const * borrow p6 = &const (&mut a); /* expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} - expected-error {{'&const' on a 'borrow' quialified type is not allowed}} */ + expected-error {{'&const' on a 'borrow' qualified type is not allowed}} */ int *borrow *borrow *borrow p7 = &mut (&mut (&mut a)); /* expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} - expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} */ + expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} */ const int *borrow *borrow *borrow p8 = &mut (&mut (&const a)); /* expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} - expected-error {{'&mut' on a 'borrow' quialified type is not allowed}}*/ - &mut p1; /* expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} + expected-error {{'&mut' on a 'borrow' qualified type is not allowed}}*/ + &mut p1; /* expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} expected-warning {{expression result unused}} */ - &const p1;/* expected-error {{'&const' on a 'borrow' quialified type is not allowed}} + &const p1;/* expected-error {{'&const' on a 'borrow' qualified type is not allowed}} expected-warning {{expression result unused}} */ - &mut p2; /* expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} + &mut p2; /* expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} expected-warning {{expression result unused}} */ - &const p2; /* expected-error {{'&const' on a 'borrow' quialified type is not allowed}} + &const p2; /* expected-error {{'&const' on a 'borrow' qualified type is not allowed}} expected-warning {{expression result unused}} */ &mut (&mut a); /* expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} - expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} */ + expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} */ &const (&const b);/* expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} - expected-error {{'&const' on a 'borrow' quialified type is not allowed}}*/ + expected-error {{'&const' on a 'borrow' qualified type is not allowed}}*/ &mut (&mut a);/* expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} - expected-error {{'&mut' on a 'borrow' quialified type is not allowed}}*/ + expected-error {{'&mut' on a 'borrow' qualified type is not allowed}}*/ &const (&const b); /* expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} - expected-error {{'&const' on a 'borrow' quialified type is not allowed}}*/ + expected-error {{'&const' on a 'borrow' qualified type is not allowed}}*/ &p1; // expected-warning {{expression result unused}} &p2; // expected-warning {{expression result unused}} & (&mut a); // expected-error {{cannot take the address of an rvalue of type 'int *borrow'}} & (&const b); // expected-error {{cannot take the address of an rvalue of type 'const int *borrow'}} struct R r = { 1, &mut a }; - struct R * borrow pr = &mut r; // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} - const struct R * borrow pr2 = &const r; // expected-error {{'&const' on a 'borrow' quialified type is not allowed}} - &const r.p1; /* expected-error {{'&const' on a 'borrow' quialified type is not allowed}} + struct R * borrow pr = &mut r; // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} + const struct R * borrow pr2 = &const r; // expected-error {{'&const' on a 'borrow' qualified type is not allowed}} + &const r.p1; /* expected-error {{'&const' on a 'borrow' qualified type is not allowed}} expected-warning {{expression result unused}} */ - &mut r.p1; /* expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} + &mut r.p1; /* expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} expected-warning {{expression result unused}} */ } \ No newline at end of file diff --git a/clang/test/BSC/Negative/Ownership/Borrow/borrow_op/borrow_op.cbs b/clang/test/BSC/Negative/Ownership/Borrow/borrow_op/borrow_op.cbs index 0339a977e339..97cb1b2cba85 100644 --- a/clang/test/BSC/Negative/Ownership/Borrow/borrow_op/borrow_op.cbs +++ b/clang/test/BSC/Negative/Ownership/Borrow/borrow_op/borrow_op.cbs @@ -59,13 +59,13 @@ int test() { ~p5; // expected-error {{invalid argument type 'const int *borrow' to unary expression}} p5 << 6; // expected-error {{invalid operands to binary expression ('const int *borrow' and 'int')}} p3 >> p4; // expected-error {{invalid operands to binary expression ('int *borrow' and 'int *borrow')}} - &mut p3; // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} + &mut p3; // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} // expected-warning@-1 {{expression result unused}} - &mut p5; // expected-error {{'&mut' on a 'borrow' quialified type is not allowed}} + &mut p5; // expected-error {{'&mut' on a 'borrow' qualified type is not allowed}} // expected-warning@-1 {{expression result unused}} - &const p3; // expected-error {{'&const' on a 'borrow' quialified type is not allowed}} + &const p3; // expected-error {{'&const' on a 'borrow' qualified type is not allowed}} // expected-warning@-1 {{expression result unused}} - &const p5; // expected-error {{'&const' on a 'borrow' quialified type is not allowed}} + &const p5; // expected-error {{'&const' on a 'borrow' qualified type is not allowed}} // expected-warning@-1 {{expression result unused}} // unary -- ++ -- Gitee From 736483ef40f0ded3bdc994ebc613d01c0e6ce56a Mon Sep 17 00:00:00 2001 From: zhangziyao Date: Wed, 27 Aug 2025 14:35:59 +0800 Subject: [PATCH 3/3] [borrow] fix the bug that caused unreasonable borrow semantic checking for uninstantiated generic functions --- clang/lib/Sema/BSC/SemaBSCOwnership.cpp | 6 ++++++ .../generic_struct_with_borrow_field.cbs | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 clang/test/BSC/Positive/Ownership/generic_struct_with_borrow_field/generic_struct_with_borrow_field.cbs diff --git a/clang/lib/Sema/BSC/SemaBSCOwnership.cpp b/clang/lib/Sema/BSC/SemaBSCOwnership.cpp index c96493b7f583..c197a8c5ff22 100644 --- a/clang/lib/Sema/BSC/SemaBSCOwnership.cpp +++ b/clang/lib/Sema/BSC/SemaBSCOwnership.cpp @@ -367,9 +367,15 @@ bool Sema::CheckBorrowQualTypeCompare(QualType LHSType, QualType RHSType) { } void Sema::CheckBorrowFunctionType(QualType ReturnTy, SmallVector ParamTys, SourceLocation SL) { + if (ReturnTy->isDependentType()) { + return; + } if (ReturnTy.hasBorrow()) { bool HasBorrowParam = false; for (QualType PT : ParamTys) { + if (PT->isDependentType()) { + return; + } if (PT.hasBorrow()) { HasBorrowParam = true; break; diff --git a/clang/test/BSC/Positive/Ownership/generic_struct_with_borrow_field/generic_struct_with_borrow_field.cbs b/clang/test/BSC/Positive/Ownership/generic_struct_with_borrow_field/generic_struct_with_borrow_field.cbs new file mode 100644 index 000000000000..0b9cecdbc675 --- /dev/null +++ b/clang/test/BSC/Positive/Ownership/generic_struct_with_borrow_field/generic_struct_with_borrow_field.cbs @@ -0,0 +1,21 @@ +// RUN: %clang %s -o %t.output +// RUN: %t.output +// expected-no-diagnostics + +struct S { + int a; + T *borrow b; +}; + +T *borrow test(struct S s) { + return s.b; +} + +int main(void) { + int a = 2; + struct S s = { 1, &mut a }; + int *borrow p = test(s); + *p = 3; + if (a == 3) return 0; + return 1; +} \ No newline at end of file -- Gitee