[clang] [clang] Improve diagnostics with incompatible VLA types (PR #101261)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 30 16:35:26 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Andrew Sukach (sookach)

<details>
<summary>Changes</summary>

This PR addresses #<!-- -->99914, by emitting a separate diagnostic for VLA's with the same bounds.

@<!-- -->AaronBallman Let me know what you think.

Thanks

---
Full diff: https://github.com/llvm/llvm-project/pull/101261.diff


3 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+24-1) 
- (added) clang/test/Sema/incompatible-vla-assignment.cpp (+9) 


``````````diff
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..e93fb869e840d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16644,7 +16644,30 @@ 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

``````````

</details>


https://github.com/llvm/llvm-project/pull/101261


More information about the cfe-commits mailing list