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

Andrew Sukach via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 20 04:57:10 PDT 2024


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

>From 2666871e019dee2314933cc60bcb4ca27d7555ba Mon Sep 17 00:00:00 2001
From: Andrew Sukach <andrewsukach at 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/Basic/Diagnostic.cpp                | 35 +++++++++++++------
 .../test/Sema/incompatible-vla-assignment.cpp |  9 +++++
 3 files changed, 37 insertions(+), 10 deletions(-)
 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 9e6d85c469d641..5533ffb4b991c3 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/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 66776daa5e1493..b7029dd6472e7c 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -1099,37 +1099,52 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
       const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
       const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
 
-      // Append before text
-      FormatDiagnostic(Argument, FirstDollar, OutStr);
-
-      // Append first type
+      // Get first type text
       TDT.PrintTree = false;
       TDT.PrintFromType = true;
+      SmallString<64> FromTypeStr, ToTypeStr;
       getDiags()->ConvertArgToString(Kind, val,
                                      StringRef(Modifier, ModifierLen),
                                      StringRef(Argument, ArgumentLen),
                                      FormattedArgs,
-                                     OutStr, QualTypeVals);
+                                     FromTypeStr, QualTypeVals);
       if (!TDT.TemplateDiffUsed)
         FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
                                                TDT.FromType));
 
-      // Append middle text
-      FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
-
-      // Append second type
+      // Get second type text
       TDT.PrintFromType = false;
       getDiags()->ConvertArgToString(Kind, val,
                                      StringRef(Modifier, ModifierLen),
                                      StringRef(Argument, ArgumentLen),
                                      FormattedArgs,
-                                     OutStr, QualTypeVals);
+                                     ToTypeStr, QualTypeVals);
       if (!TDT.TemplateDiffUsed)
         FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
                                                TDT.ToType));
 
+      // Append before text
+      FormatDiagnostic(Argument, FirstDollar, OutStr);
+
+      // Append first type
+      OutStr.append(FromTypeStr);
+
+      // Append middle text
+      FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
+
+      // Append second type
+      OutStr.append(ToTypeStr);
+
       // Append end text
       FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
+
+      if (FromTypeStr == ToTypeStr) {
+        SmallString<86> IncompatibleVLADiag(
+            "; consider using a typedef to use the same variable-length array "
+            "type for both operands");
+        OutStr.append(IncompatibleVLADiag);
+      }
+
       break;
     }
     }
diff --git a/clang/test/Sema/incompatible-vla-assignment.cpp b/clang/test/Sema/incompatible-vla-assignment.cpp
new file mode 100644
index 00000000000000..8be063631b7a8a
--- /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 pointer types assigning to 'int (*)[n]' from 'int (*)[n]'; consider using a typedef to use the same variable-length array type for both operands}}
+}



More information about the cfe-commits mailing list