From 4fa019a9d4c8f98bb3d69395867c694ace9b9271 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Wed, 23 Jul 2025 06:43:43 +0000 Subject: [PATCH 1/2] [trait] Improve error message for mismatched pointer levels in trait comparisons Previously, when comparing `trait T**` with `trait T*`, the compiler would immediately desugar both trait types and forward the comparison to the binary operator. This resulted in a low-level comparison between `struct __Trait_T*` and `struct __Trait_T`, exposing internal trait representation and producing confusing error messages that mislead users. This commit adds a pre-comparison check on pointer indirection levels. Comparisons are now only allowed between trait pointers of the same level. If the levels differ, a clear diagnostic is emitted using the original (pre-desugaring) types, improving error clarity and preventing exposure of internal data structures. --- clang/lib/Sema/BSC/SemaBSCTrait.cpp | 22 +++++++++++++------ .../multi_level_pointer_var.cbs | 2 +- .../multi_level_pointer_var.cbs | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/BSC/SemaBSCTrait.cpp b/clang/lib/Sema/BSC/SemaBSCTrait.cpp index 32669d2e768b..c6bd7593f44a 100644 --- a/clang/lib/Sema/BSC/SemaBSCTrait.cpp +++ b/clang/lib/Sema/BSC/SemaBSCTrait.cpp @@ -1186,18 +1186,26 @@ ExprResult Sema::ActOnTraitCompare(Scope *S, SourceLocation TokLoc, bool LHSIsTrait = IsTraitExpr(LHSExpr); bool RHSIsTrait = IsTraitExpr(RHSExpr); if (LHSIsTrait && RHSIsTrait) { - if (Context.hasSameType(CompleteTraitType(LHSExpr->getType()), - CompleteTraitType(RHSExpr->getType())) == false) { + QualType LHSOriginalType = CompleteTraitType(LHSExpr->getType()); + QualType RHSOriginalType = CompleteTraitType(RHSExpr->getType()); + if (Context.hasSameType(LHSOriginalType, RHSOriginalType) == false) { Diag(TokLoc, diag::ext_typecheck_comparison_of_distinct_pointers) - << CompleteTraitType(LHSExpr->getType()) - << CompleteTraitType(RHSExpr->getType()) << LHSExpr->getSourceRange() + << LHSOriginalType << RHSOriginalType << LHSExpr->getSourceRange() << RHSExpr->getSourceRange(); } - if (LHSExpr->getType()->isPointerType() || - RHSExpr->getType()->isPointerType()) + RHSExpr->getType()->isPointerType()) { + // Check pointer levels + int LHSPointerLevels = CountPointerLevels(LHSOriginalType); + int RHSPointerLevels = CountPointerLevels(RHSOriginalType); + if (LHSPointerLevels != RHSPointerLevels) { + Diag(TokLoc, diag::err_typecheck_comparison_of_distinct_pointers) + << LHSOriginalType << RHSOriginalType << LHSExpr->getSourceRange() + << RHSExpr->getSourceRange(); + return ExprError(); + } return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr); - + } SmallVector NewLHSExprs; RecordDecl *LRD = dyn_cast(LHSExpr->getType().getCanonicalType())->getDecl(); 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 413bbe8fe154..228ae1669562 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 @@ -32,7 +32,7 @@ int main() { if (q != q1) {} if (q != &p) {} // compare with trait * - if (q != p) {} // expected-error {{invalid operands to binary expression ('struct __Trait_F *' and 'struct __Trait_F')}} + if (q != p) {} // expected-error {{comparison of distinct pointer types ('trait F **' and 'trait F *')}} // expected-warning@-1 {{comparison of distinct pointer types ('trait F **' and 'trait F *')}} // compare with int diff --git a/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs b/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs index 4a785752afb4..2e7c7ec5eec9 100644 --- a/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs +++ b/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs @@ -31,7 +31,7 @@ int main() { if (q != q1) {} if (q != &p) {} // compare with trait * - if (q != p) {} // expected-error {{invalid operands to binary expression ('struct __Trait_F *' and 'struct __Trait_F')}} + if (q != p) {} // expected-error {{comparison of distinct pointer types ('trait F **' and 'trait F *')}} // expected-warning@-1 {{comparison of distinct pointer types ('trait F **' and 'trait F *')}} // compare with int if (q != num) {} // expected-warning {{comparison between pointer and integer ('struct __Trait_F *' and 'int')}} -- Gitee From 30ece4b54268743732c249a05151cb9bfb9629d0 Mon Sep 17 00:00:00 2001 From: tanhongmin Date: Mon, 28 Jul 2025 08:45:59 +0000 Subject: [PATCH 2/2] [trait] Improve error message for trait pointer comparisons with mismatched levels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, when comparing a multi-level trait pointer (e.g., `trait T**`) with a regular pointer such as `int*`, the compiler would directly forward the operation to the binary operator without proper type checking. This led to the desugared form — such as `struct __Trait_T*` — being exposed in diagnostics, revealing internal trait representation and producing confusing error messages for users. This commit enhances the comparison logic by intercepting type mismatches at the source level before desugaring. Now, the diagnostic reports the original, user-facing types (e.g., `trait T**` vs `int*`), providing a clearer and more intuitive error message that avoids leaking implementation details. --- clang/lib/Sema/SemaExpr.cpp | 21 +++++++++++++++++-- .../multi_level_pointer_var.cbs | 4 ++-- .../multi_level_pointer_var.cbs | 4 ++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0aaa1936651f..08b7853f06e8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12362,11 +12362,28 @@ static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc, if (isDesugaredTraitTypeComparison(S, LHS) && !IsError) { return; } + + // Convert desugared trait struct types back to trait types for display + QualType LHSType = LHS.get()->getType(); + QualType RHSType = RHS.get()->getType(); + + if (S.getLangOpts().BSC) { + if (S.IsDesugaredFromTraitType(LHSType)) { + LHSType = S.CompleteTraitType(LHSType); + } + if (S.IsDesugaredFromTraitType(RHSType)) { + RHSType = S.CompleteTraitType(RHSType); + } + } #endif S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_distinct_pointers : diag::ext_typecheck_comparison_of_distinct_pointers) - << LHS.get()->getType() << RHS.get()->getType() - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); +#if ENABLE_BSC + << LHSType << RHSType +#else + << LHS.get()->getType() << RHS.get()->getType() +#endif + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); } /// Returns false if the pointers are converted to a composite type, 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 228ae1669562..c70973b1980a 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 @@ -40,9 +40,9 @@ int main() { // compare with struct S if (q != s) {} // expected-error {{invalid operands to binary expression ('struct __Trait_F *' and 'struct S')}} // compare with int * - if (q != &num) {} // expected-warning {{comparison of distinct pointer types ('struct __Trait_F *' and 'int *')}} + if (q != &num) {} // expected-warning {{comparison of distinct pointer types ('trait F **' and 'int *')}} // compare with struct S * - if (q != &s) {} // expected-warning {{comparison of distinct pointer types ('struct __Trait_F *' and 'struct S *')}} + if (q != &s) {} // expected-warning {{comparison of distinct pointer types ('trait F **' and 'struct S *')}} // desugar // compare with trait pointer diff --git a/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs b/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs index 2e7c7ec5eec9..d6828f18497f 100644 --- a/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs +++ b/clang/test/BSC/Negative/Trait/r3/multi_level_pointer_var/multi_level_pointer_var.cbs @@ -38,9 +38,9 @@ int main() { // compare with struct S if (q != s) {} // expected-error {{invalid operands to binary expression ('struct __Trait_F *' and 'struct S')}} // compare with int * - if (q != &num) {} // expected-warning {{comparison of distinct pointer types ('struct __Trait_F *' and 'int *')}} + if (q != &num) {} // expected-warning {{comparison of distinct pointer types ('trait F **' and 'int *')}} // compare with struct S * - if (q != &s) {} // expected-warning {{comparison of distinct pointer types ('struct __Trait_F *' and 'struct S *')}} + if (q != &s) {} // expected-warning {{comparison of distinct pointer types ('trait F **' and 'struct S *')}} // desugar // compare with trait pointer -- Gitee