From 622735a964c96f9c09150d76407693acb3106f12 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Thu, 24 Jul 2025 02:39:28 +0000 Subject: [PATCH 1/2] [trait] Improve error message when initializing trait with incompatible type Previously, when initializing a trait-typed variable with a pointer of a different trait type, the compiler produced an error referencing the underlying struct types (e.g., `struct __Trait_X` vs `struct __Trait_Y`). This exposed internal implementation details, including those related to `owned` and `borrow` semantics, leading to confusing and user-unfriendly diagnostics. This commit enhances the error reporting by detecting type mismatches at the syntactic (pre-desugaring) level. The new diagnostic now reports the original trait types involved, avoiding exposure of low-level structures and providing a clearer, more intuitive error message. --- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 3 ++- .../Ownership/Owned/owned_trait_decl/owned_trait_decl.cbs | 2 +- .../Trait/GenericTrait/trait_cast_trait/trait_cast_trait.cbs | 4 ++-- .../Negative/Trait/r3/trait_assignment/trait_assignment.cbs | 2 +- .../Negative/Trait/r3/trait_cast_trait/trait_cast_trait.cbs | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index be4778e7f7d5..0d399e7e0f34 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -772,7 +772,8 @@ VarDecl *Sema::ActOnDesugarTraitInstance(Decl *D) { } const PointerType *PT = dyn_cast_or_null(T.getTypePtr()); if (!PT) { - Diag(UO->getBeginLoc(), diag::err_type_has_not_impl_trait) << OriginQT << T; + Diag(UO->getBeginLoc(), diag::err_type_has_not_impl_trait) + << OriginQT << CompleteTraitType(T); return nullptr; } diff --git a/clang/test/BSC/Negative/Ownership/Owned/owned_trait_decl/owned_trait_decl.cbs b/clang/test/BSC/Negative/Ownership/Owned/owned_trait_decl/owned_trait_decl.cbs index 93602cc25e6a..e8c1fb30813c 100644 --- a/clang/test/BSC/Negative/Ownership/Owned/owned_trait_decl/owned_trait_decl.cbs +++ b/clang/test/BSC/Negative/Ownership/Owned/owned_trait_decl/owned_trait_decl.cbs @@ -28,5 +28,5 @@ void test2(int x, float y, double d) { trait T* owned t2 = t1; trait U* owned u1 = (int* owned)&x; trait T* owned t3 = u1; // expected-error {{incompatible owned types, cannot cast 'struct __Trait_U_Owned' to 'trait T *owned'}} - // expected-error@-1 {{expected a pointer type which has implemented 'trait T', found 'struct __Trait_U_Owned'}} + // expected-error@-1 {{expected a pointer type which has implemented 'trait T', found 'trait U *'}} } \ No newline at end of file diff --git a/clang/test/BSC/Negative/Trait/GenericTrait/trait_cast_trait/trait_cast_trait.cbs b/clang/test/BSC/Negative/Trait/GenericTrait/trait_cast_trait/trait_cast_trait.cbs index 2372520ed7d9..e195b824ae62 100644 --- a/clang/test/BSC/Negative/Trait/GenericTrait/trait_cast_trait/trait_cast_trait.cbs +++ b/clang/test/BSC/Negative/Trait/GenericTrait/trait_cast_trait/trait_cast_trait.cbs @@ -7,8 +7,8 @@ trait G {}; void test() { trait G *g; - trait F *q = g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'struct __Trait_G'}} - trait F *q1 = (trait F *)g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'struct __Trait_G'}} + trait F *q = g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'trait G *'}} + trait F *q1 = (trait F *)g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'trait G *'}} q = g; // expected-error {{assigning to 'struct __Trait_F' from incompatible type 'trait G *'}} q1 = (trait F *)g; // expected-error {{assigning to 'struct __Trait_F' from incompatible type 'trait G *'}} } \ No newline at end of file diff --git a/clang/test/BSC/Negative/Trait/r3/trait_assignment/trait_assignment.cbs b/clang/test/BSC/Negative/Trait/r3/trait_assignment/trait_assignment.cbs index 9e7daaafa147..52cf3014a951 100644 --- a/clang/test/BSC/Negative/Trait/r3/trait_assignment/trait_assignment.cbs +++ b/clang/test/BSC/Negative/Trait/r3/trait_assignment/trait_assignment.cbs @@ -11,6 +11,6 @@ trait F* f() { int main() { int m = 0; - trait F* b = f(); // expected-error {{expected a pointer type which has implemented 'trait F', found 'struct __Trait_F'}} + trait F* b = f(); // expected-error {{expected a pointer type which has implemented 'trait F', found 'trait F *'}} return 0; } \ No newline at end of file diff --git a/clang/test/BSC/Negative/Trait/r3/trait_cast_trait/trait_cast_trait.cbs b/clang/test/BSC/Negative/Trait/r3/trait_cast_trait/trait_cast_trait.cbs index 077cc6573fd3..1f4e27a9b908 100644 --- a/clang/test/BSC/Negative/Trait/r3/trait_cast_trait/trait_cast_trait.cbs +++ b/clang/test/BSC/Negative/Trait/r3/trait_cast_trait/trait_cast_trait.cbs @@ -7,8 +7,8 @@ trait G {}; void test() { trait G *g; - trait F *q = g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'struct __Trait_G'}} - trait F *q1 = (trait F *)g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'struct __Trait_G'}} + trait F *q = g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'trait G *'}} + trait F *q1 = (trait F *)g; // expected-error {{expected a pointer type which has implemented 'trait F', found 'trait G *'}} q = g; // expected-error {{assigning to 'struct __Trait_F' from incompatible type 'trait G *'}} q1 = (trait F *)g; // expected-error {{assigning to 'struct __Trait_F' from incompatible type 'trait G *'}} } \ No newline at end of file -- Gitee From aaec9431b69298ca4688fd8f27b4e82c9ca60586 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Thu, 24 Jul 2025 07:35:32 +0000 Subject: [PATCH 2/2] [trait] Prevent coredump during initialization from multi-level trait pointers Previously, initializing a trait-typed variable with a multi-level trait pointer (e.g., `trait T**` to `trait T`) would cause a coredump due to missing desugaring logic for pointer levels in the initialization path. The compiler failed to properly handle type canonicalization, leading to a null dereference or assertion failure. This commit adds proper desugaring and pointer-level validation during trait initialization. The type system now correctly processes nested pointer conversions before initialization, preventing the crash and ensuring safe semantic analysis. --- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 20 ++++++++++++++++++- .../multi_level_pointer_var.cbs | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index 0d399e7e0f34..32669d2e768b 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -672,6 +672,15 @@ QualType Sema::DesugarTraitToStructTrait(TraitDecl *TD, QualType T, return RT; } +static int CountPointerLevels(QualType T) { + int PointerLevels = 0; + while (T->isPointerType()) { + T = T->getPointeeType(); + ++PointerLevels; + } + return PointerLevels; +} + // In this function, we aim to assign the Trait_xxx struct, // for example, we have desugared as follows: //`struct Trait_I { @@ -757,7 +766,7 @@ VarDecl *Sema::ActOnDesugarTraitInstance(Decl *D) { else if (VD->getType().isBorrowQualified()) TraitTy = QualType(TD->getBorrowTrait()->getTypeForDecl(), 0); else - TraitTy = QualType(TD->getTrait()->getTypeForDecl(), 0);; + TraitTy = QualType(TD->getTrait()->getTypeForDecl(), 0); if (dyn_cast(TraitTy)) { TraitTy = CompleteRecordType(TD->getTrait(), NewVD->getTypeSourceInfo()); } @@ -767,6 +776,15 @@ VarDecl *Sema::ActOnDesugarTraitInstance(Decl *D) { // trait I **c = (trait F **)a; // @endcode if (!TraitTy.isNull() && Context.hasSameType(InnerTy, TraitTy)) { + if (CountPointerLevels(Context.getPointerType(OriginQT)) != + CountPointerLevels(CompleteTraitType(T))) { + Diag(UO->getBeginLoc(), + diag::err_typecheck_convert_incompatible_pointer) + << Context.getPointerType(OriginQT) << CompleteTraitType(T) + << 4 // operation type: 4 = initializing + << 0; // hint type: 0 = no additional hint + return nullptr; + } AddInitializerToDecl(NewVD, UO, false); return NewVD; } diff --git a/clang/test/BSC/Negative/Trait/GenericTrait/multi_level_pointer_var/multi_level_pointer_var.cbs b/clang/test/BSC/Negative/Trait/GenericTrait/multi_level_pointer_var/multi_level_pointer_var.cbs index 9b04eb2c83d5..413bbe8fe154 100644 --- a/clang/test/BSC/Negative/Trait/GenericTrait/multi_level_pointer_var/multi_level_pointer_var.cbs +++ b/clang/test/BSC/Negative/Trait/GenericTrait/multi_level_pointer_var/multi_level_pointer_var.cbs @@ -21,6 +21,7 @@ int main() { struct S s; int num = 1; trait F *p = &s; + trait F **pp = p; // expected-error {{incompatible pointer types initializing 'trait F **' with an expression of type 'trait F *'}} trait F **q = &p; trait F **q1 = &p; -- Gitee