[Clang] Add note for bad conversion when expression is pointer to forward-declared type
Differential Revision: https://reviews.llvm.org/D85390
This commit is contained in:
@@ -2005,6 +2005,8 @@ def err_init_conversion_failed : Error<
|
||||
"|: different return type%diff{ ($ vs $)|}5,6"
|
||||
"|: different qualifiers (%5 vs %6)"
|
||||
"|: different exception specifications}4">;
|
||||
def note_forward_class_conversion : Note<"%0 is not defined, but forward "
|
||||
"declared here; conversion would be valid if it's derived from %1">;
|
||||
|
||||
def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot "
|
||||
"bind to lvalue of type $|cannot bind to incompatible lvalue}0,1">;
|
||||
|
||||
@@ -8707,6 +8707,16 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
|
||||
if (entity.getKind() == InitializedEntity::EK_Result)
|
||||
S.EmitRelatedResultTypeNoteForReturn(destType);
|
||||
}
|
||||
QualType fromType = op->getType();
|
||||
auto *fromDecl = fromType.getTypePtr()->getPointeeCXXRecordDecl();
|
||||
auto *destDecl = destType.getTypePtr()->getPointeeCXXRecordDecl();
|
||||
if (fromDecl && destDecl && fromDecl->getDeclKind() == Decl::CXXRecord &&
|
||||
destDecl->getDeclKind() == Decl::CXXRecord &&
|
||||
!fromDecl->isInvalidDecl() && !destDecl->isInvalidDecl() &&
|
||||
!fromDecl->hasDefinition())
|
||||
S.Diag(fromDecl->getLocation(), diag::note_forward_class_conversion)
|
||||
<< S.getASTContext().getTagDeclType(fromDecl)
|
||||
<< S.getASTContext().getTagDeclType(destDecl);
|
||||
}
|
||||
|
||||
static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
|
||||
|
||||
@@ -78,7 +78,8 @@ void testAnonymousNotMerged() {
|
||||
|
||||
// expected-note@Inputs/namespaces-right.h:60 {{passing argument to parameter here}}
|
||||
// expected-note@Inputs/namespaces-right.h:67 {{passing argument to parameter here}}
|
||||
|
||||
// expected-note@Inputs/namespaces-left.h:63 {{'N11::(anonymous namespace)::Foo' is not defined, but forward declared here; conversion would be valid if it's derived from 'N11::(anonymous namespace)::Foo'}}
|
||||
// expected-note@Inputs/namespaces-left.h:70 {{'N12::(anonymous namespace)::Foo' is not defined, but forward declared here; conversion would be valid if it's derived from 'N12::(anonymous namespace)::Foo'}}
|
||||
// Test that bringing in one name from an overload set does not hide the rest.
|
||||
void testPartialImportOfOverloadSet() {
|
||||
void (*p)() = N13::p;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace NS {
|
||||
}
|
||||
|
||||
void test_X_elab(NS::X x) {
|
||||
struct S4 *s4 = 0;
|
||||
struct S4 *s4 = 0; // expected-note{{'S4' is not defined, but forward declared here; conversion would be valid if it's derived from 'NS::S4'}}
|
||||
x.test_elab2(s4); // expected-error{{cannot initialize a parameter of type 'NS::S4 *' with an lvalue of type 'struct S4 *'}}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
class A1 {};
|
||||
class B1; // expected-note{{'B1' is not defined, but forward declared here; conversion would be valid if it's derived from 'A1'}}
|
||||
B1 *b1;
|
||||
A1 *a1 = b1; // expected-error{{cannot initialize a variable of type 'A1 *' with an lvalue of type 'B1 *'}}
|
||||
|
||||
template <class C> class A2 {};
|
||||
template <class C> class B2;
|
||||
B2<int> *b2;
|
||||
A2<int> *a2 = b2; // expected-error{{cannot initialize a variable of type 'A2<int> *' with an lvalue of type 'B2<int> *'}}
|
||||
Reference in New Issue
Block a user