https://github.com/sookach updated https://github.com/llvm/llvm-project/pull/101261
>From e7d15a3d29715e4922eb542d46cdc6d081ad740e Mon Sep 17 00:00:00 2001 From: Andrew Sukach <andrewsuk...@gmail.com> Date: Tue, 30 Jul 2024 19:31:41 -0400 Subject: [PATCH] [clang] Improve diagnostics with incompatible VLA types --- .../clang/Basic/DiagnosticSemaKinds.td | 3 +++ clang/lib/Sema/SemaExpr.cpp | 27 ++++++++++++++++++- .../test/Sema/incompatible-vla-assignment.cpp | 9 +++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 clang/test/Sema/incompatible-vla-assignment.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9e6d85c469d64..5533ffb4b991c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8643,6 +8643,9 @@ def err_typecheck_convert_incompatible_pointer : Error< "; take the address with &|" "; remove *|" "; remove &}3">; +def err_typecheck_convert_incompatible_vla : Error< + "incompatible assignment of pointers of variable-length array type %0" + "; consider using a typedef to use the same variable-length array type for both operands">; def err_typecheck_convert_incompatible_function_pointer : Error< "incompatible function pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 74c0e01705905..84129a0f1c833 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16644,7 +16644,32 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (Action == AA_Passing_CFAudited) { DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer; } else if (getLangOpts().CPlusPlus) { - DiagKind = diag::err_typecheck_convert_incompatible_pointer; + DiagKind = [this, &SrcType, &DstType] { + const VariableArrayType *SrcTypeVLA = nullptr, *DstTypeVLA = nullptr; + if (const PointerType *P = SrcType->getAs<PointerType>()) + SrcTypeVLA = Context.getAsVariableArrayType(P->getPointeeType()); + if (const PointerType *P = DstType->getAs<PointerType>()) + DstTypeVLA = Context.getAsVariableArrayType(P->getPointeeType()); + + if (SrcTypeVLA == nullptr || DstTypeVLA == nullptr) + return diag::err_typecheck_convert_incompatible_pointer; + + DeclRefExpr *SrcSizeExpr = nullptr, *DstSizeExpr = nullptr; + if (ImplicitCastExpr *I = + dyn_cast<ImplicitCastExpr>(SrcTypeVLA->getSizeExpr())) + SrcSizeExpr = dyn_cast<DeclRefExpr>(I->getSubExpr()); + if (ImplicitCastExpr *I = + dyn_cast<ImplicitCastExpr>(DstTypeVLA->getSizeExpr())) + DstSizeExpr = dyn_cast<DeclRefExpr>(I->getSubExpr()); + + if (SrcSizeExpr == nullptr || DstSizeExpr == nullptr) + return diag::err_typecheck_convert_incompatible_pointer; + + return SrcSizeExpr->getDecl()->getName() == + DstSizeExpr->getDecl()->getName() + ? diag::err_typecheck_convert_incompatible_vla + : diag::err_typecheck_convert_incompatible_pointer; + }(); isInvalid = true; } else { DiagKind = diag::ext_typecheck_convert_incompatible_pointer; diff --git a/clang/test/Sema/incompatible-vla-assignment.cpp b/clang/test/Sema/incompatible-vla-assignment.cpp new file mode 100644 index 0000000000000..9cecaacb6c250 --- /dev/null +++ b/clang/test/Sema/incompatible-vla-assignment.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void func(int n) { + int grp[n][n]; + int (*ptr)[n]; + + for (int i = 0; i < n; i++) + ptr = &grp[i]; // expected-error {{incompatible assignment of pointers of variable-length array type 'int (*)[n]'; consider using a typedef to use the same variable-length array type for both operands}} +} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits