@@ -3801,6 +3801,131 @@ void MissingMemberFailure::diagnoseUnsafeCxxMethod(SourceLoc loc,
38013801 !isa_and_nonnull<clang::CXXRecordDecl>(
38023802 baseType->getAnyNominal ()->getClangDecl ()))
38033803 return ;
3804+
3805+ if (name.getBaseIdentifier ().str () == " getFromPointer" ||
3806+ name.getBaseIdentifier ().str () == " isValid" ||
3807+ name.getBaseIdentifier ().str () == " __dataUnsafe" ||
3808+ name.getBaseIdentifier ().str () == " __getOpaquePointerValueUnsafe" ||
3809+ name.getBaseIdentifier ().str () == " __getStartUnsafe" ||
3810+ name.getBaseIdentifier ().str () == " __c_strUnsafe" ) {
3811+ // OK, we did not find a member that we probably should have.
3812+ // Dump the world.
3813+ llvm::dbgs () << " ====================================================\n " ;
3814+ llvm::dbgs () << " ====================================================\n\n " ;
3815+ llvm::dbgs () << " Hello! You have unfortuantly stubled across an interop bug that we have been trying to track down for a while. Please reach out to Zoe Carver and provide a link to this build. You can re-run this build and it should work next time. Sorry for the inconvience.\n\n " ;
3816+ llvm::dbgs () << " ====================================================\n " ;
3817+ llvm::dbgs () << " ====================================================\n\n " ;
3818+
3819+ llvm::dbgs () << " THE NAME: " ; name.dump ();
3820+
3821+ llvm::dbgs () << " ====================================================\n " ;
3822+ llvm::dbgs () << " ====================================================\n\n " ;
3823+
3824+ auto cxxRecord = cast<clang::CXXRecordDecl>(baseType->getAnyNominal ()->getClangDecl ());
3825+ llvm::dbgs () << " CXX RECORD: " ; cxxRecord->dump ();
3826+
3827+ llvm::dbgs () << " ====================================================\n " ;
3828+ llvm::dbgs () << " ====================================================\n\n " ;
3829+
3830+ auto dumpRedecls = [](const clang::CXXRecordDecl *cxxRecordToDump) {
3831+ llvm::dbgs () << " REDECLS:\n " ;
3832+ unsigned redeclIdx = 0 ;
3833+ for (auto redecl : cxxRecordToDump->redecls ()) {
3834+ llvm::dbgs () << " REDECL(" << redeclIdx << " ): " ; redecl->dump ();
3835+ redeclIdx++;
3836+ }
3837+ };
3838+
3839+ dumpRedecls (cxxRecord);
3840+
3841+ llvm::dbgs () << " ====================================================\n " ;
3842+ llvm::dbgs () << " ====================================================\n\n " ;
3843+ if (name.getBaseIdentifier ().str () == " getFromPointer" ||
3844+ name.getBaseIdentifier ().str () == " isValid" ) {
3845+ llvm::dbgs () << " LOOKUP UNSAFE VERSION:\n " ;
3846+ auto unsafeId =
3847+ ctx.getIdentifier (" __" + name.getBaseIdentifier ().str ().str () + " Unsafe" );
3848+ for (auto found :
3849+ baseType->getAnyNominal ()->lookupDirect (DeclBaseName (unsafeId))) {
3850+ llvm::dbgs () << " **FOUND UNSAFE VERSION**\n " ;
3851+ llvm::dbgs () << " UNSAFE: " ;
3852+ found->dump ();
3853+
3854+ if (auto cxxMethod = dyn_cast_or_null<clang::CXXMethodDecl>(found->getClangDecl ())) {
3855+ llvm::dbgs () << " FOUND CXX METHOD." ;
3856+ auto returnType = cxxMethod->getReturnType ();
3857+ llvm::dbgs () << " CXX METHOD RETURN TYPE: " ;
3858+ returnType->dump ();
3859+
3860+ llvm::dbgs () << " CAN RETURN TYPE: " ;
3861+ returnType->getCanonicalTypeUnqualified ().dump ();
3862+
3863+ if (auto recordType = dyn_cast<clang::RecordType>(returnType)) {
3864+ dumpRedecls (returnType->getAsCXXRecordDecl ());
3865+ } else {
3866+ llvm::dbgs () << " NOT A RECORD TYPE\n " ;
3867+ }
3868+ }
3869+ }
3870+ } else {
3871+ std::string safeName;
3872+ if (name.getBaseIdentifier ().str () == " __dataUnsafe" )
3873+ safeName = " data" ;
3874+ if (name.getBaseIdentifier ().str () == " __getOpaquePointerValueUnsafe" )
3875+ safeName = " getOpaquePointerValue" ;
3876+ if (name.getBaseIdentifier ().str () == " __getStartUnsafe" )
3877+ safeName = " getStart" ;
3878+ if (name.getBaseIdentifier ().str () == " __c_strUnsafe" )
3879+ safeName = " c_str" ;
3880+
3881+ auto safeId = ctx.getIdentifier (safeName);
3882+ for (auto found :
3883+ baseType->getAnyNominal ()->lookupDirect (DeclBaseName (safeId))) {
3884+ llvm::dbgs () << " **FOUND SAFE VERSION**\n " ;
3885+ llvm::dbgs () << " UNSAFE: " ;
3886+ found->dump ();
3887+
3888+ if (auto cxxMethod = dyn_cast_or_null<clang::CXXMethodDecl>(found->getClangDecl ())) {
3889+ llvm::dbgs () << " FOUND CXX METHOD." ;
3890+ auto returnType = cxxMethod->getReturnType ();
3891+ llvm::dbgs () << " CXX METHOD RETURN TYPE: " ;
3892+ returnType->dump ();
3893+
3894+ llvm::dbgs () << " CAN RETURN TYPE: " ;
3895+ returnType->getCanonicalTypeUnqualified ().dump ();
3896+
3897+ if (auto recordType = dyn_cast<clang::RecordType>(returnType)) {
3898+ dumpRedecls (returnType->getAsCXXRecordDecl ());
3899+ } else {
3900+ llvm::dbgs () << " NOT A RECORD TYPE\n " ;
3901+ }
3902+ }
3903+ }
3904+ }
3905+
3906+ llvm::dbgs () << " ====================================================\n " ;
3907+ llvm::dbgs () << " ====================================================\n\n " ;
3908+ llvm::dbgs () << " (IMPORTED) SWIFT TYPE: " ;
3909+ baseType->dump ();
3910+
3911+ llvm::dbgs () << " (IMPORTED) SWIFT DECL: " ;
3912+ baseType->getAnyNominal ()->dump ();
3913+
3914+ // And for my final trick, I will dump the whole lookup table.
3915+ llvm::dbgs () << " ====================================================\n " ;
3916+ llvm::dbgs () << " ====================================================\n\n " ;
3917+ llvm::dbgs () << " LOOKUP TABLE: " ;
3918+
3919+ if (auto clangModule = cxxRecord->getOwningModule ()) {
3920+ dumpSwiftLookupTable (ctx.getClangModuleLoader ()->findLookupTable (clangModule));
3921+ } else {
3922+ llvm::dbgs () << " NO MODULE\n " ;
3923+ }
3924+
3925+ llvm::dbgs () << " ====================================================\n " ;
3926+ llvm::dbgs () << " DBUG DUMP DONE\n " ;
3927+ llvm::dbgs () << " ====================================================\n\n " ;
3928+ }
38043929
38053930 auto unsafeId =
38063931 ctx.getIdentifier (" __" + name.getBaseIdentifier ().str ().str () + " Unsafe" );
0 commit comments