Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down
22 changes: 16 additions & 6 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Comment on lines +9808 to +9821
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about something along these lines (with comments)?

PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed);
{
  llvm::SaveAndRestore _(DestType);
  unsigned EKind = (unsigned)Entity.getKind() + 1;
  if (Entity.getKind() == InitializedEntity::EK_Variable &&
        DestType.isConstQualified()) {
    EKind = 0;
    DestType.removeLocalConst();
  }

  PDiag << EKind << DestType << ...;
}
S.HandleFunctionTypeMismatch(PDiag, ...);


S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
S.Diag(Kind.getLocation(), PDiag);
emitBadConversionNotes(S, Entity, Args[0]);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/constant-expression-cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, "");
Expand Down
11 changes: 11 additions & 0 deletions clang/test/SemaCXX/err_init_conversion_failed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 *'}}
}