Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

agentcooper
Copy link
Contributor

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Feb 17, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Feb 17, 2024

@llvm/pr-subscribers-clang

Author: Artem Tyurin (agentcooper)

Changes

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.


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

4 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1-1)
  • (modified) clang/lib/Sema/SemaInit.cpp (+16-6)
  • (modified) clang/test/SemaCXX/constant-expression-cxx11.cpp (+1-1)
  • (modified) clang/test/SemaCXX/err_init_conversion_failed.cpp (+11)
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..359d840070f2c4 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@-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@-1{{cannot initialize a constant of type 'int'}}
+
+  int* const c = (void)0;
+  // expected-error@-1{{cannot initialize a constant of type 'int *'}}
+
+  const int* b = (void)0;
+  // expected-error@-1{{cannot initialize a variable of type 'const int *'}}
+}

@agentcooper
Copy link
Contributor Author

@cjdb Hey Christopher, I'm curious to hear your thoughts on this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Simplify initialisation diagnostic when types are cv-qualified
2 participants