This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGc354b2e3bfe6: [Clang] Add note for bad conversion when expression is pointer to forward… (authored by zequanwu).
Changed prior to commit: https://reviews.llvm.org/D85390?vs=283949&id=283957#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D85390/new/ https://reviews.llvm.org/D85390 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaInit.cpp clang/test/Modules/namespaces.cpp clang/test/SemaCXX/elaborated-type-specifier.cpp clang/test/SemaCXX/pointer-forward-declared-class-conversion.cpp Index: clang/test/SemaCXX/pointer-forward-declared-class-conversion.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/pointer-forward-declared-class-conversion.cpp @@ -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> *'}} Index: clang/test/SemaCXX/elaborated-type-specifier.cpp =================================================================== --- clang/test/SemaCXX/elaborated-type-specifier.cpp +++ clang/test/SemaCXX/elaborated-type-specifier.cpp @@ -26,7 +26,7 @@ } 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 *'}} } Index: clang/test/Modules/namespaces.cpp =================================================================== --- clang/test/Modules/namespaces.cpp +++ clang/test/Modules/namespaces.cpp @@ -78,7 +78,8 @@ // 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; Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -8707,6 +8707,16 @@ 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, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2005,6 +2005,8 @@ "|: 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">;
Index: clang/test/SemaCXX/pointer-forward-declared-class-conversion.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/pointer-forward-declared-class-conversion.cpp @@ -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> *'}} Index: clang/test/SemaCXX/elaborated-type-specifier.cpp =================================================================== --- clang/test/SemaCXX/elaborated-type-specifier.cpp +++ clang/test/SemaCXX/elaborated-type-specifier.cpp @@ -26,7 +26,7 @@ } 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 *'}} } Index: clang/test/Modules/namespaces.cpp =================================================================== --- clang/test/Modules/namespaces.cpp +++ clang/test/Modules/namespaces.cpp @@ -78,7 +78,8 @@ // 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; Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -8707,6 +8707,16 @@ 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, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2005,6 +2005,8 @@ "|: 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">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits