[clang] [clang][Sema] Simplify err_init_conversion_failed diagnostic message for const variables (PR #82109)

Artem Tyurin via cfe-commits cfe-commits at lists.llvm.org
Sat Feb 17 06:21:52 PST 2024


https://github.com/agentcooper created https://github.com/llvm/llvm-project/pull/82109

Fixes #73399.

I initially tried to create a new `EntityKind` enum case to represent constants as it makes it easier to use `Entity.getKind()` with the diagnostic message. But in the end I've decided against it, as the new case needs to be handled in many places and feels error-prone.

>From 114a6b7a5c1b9993e06d49bfd0c377baaef2d7cb Mon Sep 17 00:00:00 2001
From: Artem Tyurin <artem.tyurin at gmail.com>
Date: Sat, 17 Feb 2024 15:16:17 +0100
Subject: [PATCH 1/2] [clang][Sema] Simplify err_init_conversion_failed
 diagnostic message for const variables

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 +-
 clang/lib/Sema/SemaInit.cpp                   | 22 ++++++++++++++-----
 .../SemaCXX/constant-expression-cxx11.cpp     |  2 +-
 .../SemaCXX/err_init_conversion_failed.cpp    | 11 ++++++++++
 4 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..1c9a69167c28d1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2204,7 +2204,7 @@ def err_destructor_template : Error<
 
 // C++ initialization
 def err_init_conversion_failed : Error<
-  "cannot initialize %select{a variable|a parameter|template parameter|"
+  "cannot initialize %select{a constant|a variable|a parameter|template parameter|"
   "return object|statement expression result|an "
   "exception object|a member subobject|an array element|a new value|a value|a "
   "base class|a constructor delegation|a vector element|a block element|a "
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b6de06464cd6f3..c1846d9a80c8f2 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -9804,12 +9804,22 @@ bool InitializationSequence::Diagnose(Sema &S,
 
   case FK_ConversionFailed: {
     QualType FromType = OnlyArg->getType();
-    PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
-      << (int)Entity.getKind()
-      << DestType
-      << OnlyArg->isLValue()
-      << FromType
-      << Args[0]->getSourceRange();
+
+    // NOTE: need to be in sync with err_init_conversion_failed
+    const auto TotalSpecialKinds = 1;
+
+    PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed);
+    if (Entity.getKind() == InitializedEntity::EK_Variable &&
+        DestType.isConstQualified()) {
+      QualType NonConstDestType = DestType;
+      NonConstDestType.removeLocalConst();
+      PDiag << 0 /* a constant */
+            << NonConstDestType;
+    } else {
+      PDiag << (TotalSpecialKinds + (int)Entity.getKind()) << DestType;
+    }
+    PDiag << OnlyArg->isLValue() << FromType << Args[0]->getSourceRange();
+
     S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
     S.Diag(Kind.getLocation(), PDiag);
     emitBadConversionNotes(S, Entity, Args[0]);
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 9e2ae07cbe4c9c..19ab0cc27cc015 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -901,7 +901,7 @@ static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, "");
 
 // Core issue 903: we do not perform constant evaluation when checking for a
 // null pointer in C++11. Just check for an integer literal with value 0.
-constexpr Base *nullB = 42 - 6 * 7; // expected-error {{cannot initialize a variable of type 'Base *const' with an rvalue of type 'int'}}
+constexpr Base *nullB = 42 - 6 * 7; // expected-error {{cannot initialize a constant of type 'Base *' with an rvalue of type 'int'}}
 constexpr Base *nullB1 = 0;
 static_assert((Bottom*)nullB == 0, "");
 static_assert((Derived*)nullB1 == 0, "");
diff --git a/clang/test/SemaCXX/err_init_conversion_failed.cpp b/clang/test/SemaCXX/err_init_conversion_failed.cpp
index e31f215b4528cb..107ba1bbf51969 100644
--- a/clang/test/SemaCXX/err_init_conversion_failed.cpp
+++ b/clang/test/SemaCXX/err_init_conversion_failed.cpp
@@ -59,3 +59,14 @@ void test_15() {
   // expected-error-re at -1{{cannot initialize a member subobject of type 'void (template_test::S::*)(const int &){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (template_test::S::*)(int){{( __attribute__\(\(thiscall\)\))?}}': type mismatch at 1st parameter ('const int &' vs 'int')}}
 }
 }
+
+void test_16() {
+  const int a = (void)0;
+  // expected-error at -1{{cannot initialize a constant of type 'int'}}
+
+  int* const c = (void)0;
+  // expected-error at -1{{cannot initialize a constant of type 'int *'}}
+
+  const int* b = (void)0;
+  // expected-error at -1{{cannot initialize a variable of type 'const int *'}}
+}
\ No newline at end of file

>From b430a73246ef66e5a48bdb73fbd0fc8a8aba0752 Mon Sep 17 00:00:00 2001
From: Artem Tyurin <artem.tyurin at gmail.com>
Date: Sat, 17 Feb 2024 15:18:23 +0100
Subject: [PATCH 2/2] Add newline

---
 clang/test/SemaCXX/err_init_conversion_failed.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/SemaCXX/err_init_conversion_failed.cpp b/clang/test/SemaCXX/err_init_conversion_failed.cpp
index 107ba1bbf51969..359d840070f2c4 100644
--- a/clang/test/SemaCXX/err_init_conversion_failed.cpp
+++ b/clang/test/SemaCXX/err_init_conversion_failed.cpp
@@ -69,4 +69,4 @@ void test_16() {
 
   const int* b = (void)0;
   // expected-error at -1{{cannot initialize a variable of type 'const int *'}}
-}
\ No newline at end of file
+}



More information about the cfe-commits mailing list