@@ -5707,19 +5707,74 @@ RValue RValueEmitter::visitInOutToPointerExpr(InOutToPointerExpr *E,
57075707 return RValue (SGF, E, ptr);
57085708}
57095709
5710+ // / Implicit conversion from a nontrivial inout type to a raw pointer are
5711+ // / dangerous. For example:
5712+ // /
5713+ // / func bar(_ p: UnsafeRawPointer) { ... }
5714+ // / func foo(object: inout AnyObject) {
5715+ // / bar(&object)
5716+ // / }
5717+ // /
5718+ // / These conversions should be done explicitly.
5719+ // /
5720+ static void diagnoseImplicitRawConversion (Type sourceTy, Type pointerTy,
5721+ SILLocation loc,
5722+ SILGenFunction &SGF) {
5723+ // Array conversion does not always go down the ArrayConverter
5724+ // path. Recognize the Array source type here both for ArrayToPointer and
5725+ // InoutToPointer cases and diagnose on the element type.
5726+ Type eltTy = sourceTy->isArrayType ();
5727+ if (!eltTy)
5728+ eltTy = sourceTy;
5729+
5730+ if (SGF.getLoweredType (eltTy).isTrivial (SGF.F ))
5731+ return ;
5732+
5733+ auto *SM = SGF.getModule ().getSwiftModule ();
5734+ if (auto *fixedWidthIntegerDecl = SM->getASTContext ().getProtocol (
5735+ KnownProtocolKind::FixedWidthInteger)) {
5736+ if (SM->conformsToProtocol (eltTy, fixedWidthIntegerDecl))
5737+ return ;
5738+ }
5739+
5740+ PointerTypeKind kindOfPtr;
5741+ auto pointerElt = pointerTy->getAnyPointerElementType (kindOfPtr);
5742+ assert (!pointerElt.isNull () && " expected an unsafe pointer type" );
5743+
5744+ // The element type may contain a reference. Disallow conversion to a "raw"
5745+ // pointer type. Consider Int8/UInt8 to be raw pointers. Trivial element types
5746+ // are filtered out above, so Int8/UInt8 pointers can't match the source
5747+ // type. But the type checker may have allowed these for direct C calls, in
5748+ // which Int8/UInt8 are equivalent to raw pointers..
5749+ if (!(pointerElt->isVoid () || pointerElt->isInt8 () || pointerElt->isUInt8 ()))
5750+ return ;
5751+
5752+ if (sourceTy->isString ()) {
5753+ SGF.SGM .diagnose (loc, diag::nontrivial_string_to_rawpointer_conversion,
5754+ pointerTy);
5755+ } else {
5756+ SGF.SGM .diagnose (loc, diag::nontrivial_to_rawpointer_conversion, sourceTy,
5757+ pointerTy, eltTy);
5758+ }
5759+ }
5760+
57105761// / Convert an l-value to a pointer type: unsafe, unsafe-mutable, or
57115762// / autoreleasing-unsafe-mutable.
57125763ManagedValue SILGenFunction::emitLValueToPointer (SILLocation loc, LValue &&lv,
57135764 PointerAccessInfo pointerInfo) {
57145765 assert (pointerInfo.AccessKind == lv.getAccessKind ());
57155766
5767+ diagnoseImplicitRawConversion (lv.getSubstFormalType (),
5768+ pointerInfo.PointerType , loc, *this );
5769+
57165770 // The incoming lvalue should be at the abstraction level of T in
57175771 // Unsafe*Pointer<T>. Reabstract it if necessary.
57185772 auto opaqueTy = AbstractionPattern::getOpaque ();
57195773 auto loweredTy = getLoweredType (opaqueTy, lv.getSubstFormalType ());
57205774 if (lv.getTypeOfRValue ().getASTType () != loweredTy.getASTType ()) {
57215775 lv.addSubstToOrigComponent (opaqueTy, loweredTy);
57225776 }
5777+
57235778 switch (pointerInfo.PointerKind ) {
57245779 case PTK_UnsafeMutablePointer:
57255780 case PTK_UnsafePointer:
@@ -5833,6 +5888,9 @@ SILGenFunction::emitArrayToPointer(SILLocation loc, ManagedValue array,
58335888 firstSubMap, secondSubMap, CombineSubstitutionMaps::AtIndex, 1 , 0 ,
58345889 genericSig);
58355890
5891+ diagnoseImplicitRawConversion (accessInfo.ArrayType , accessInfo.PointerType ,
5892+ loc, *this );
5893+
58365894 SmallVector<ManagedValue, 2 > resultScalars;
58375895 emitApplyOfLibraryIntrinsic (loc, converter, subMap, array, SGFContext ())
58385896 .getAll (resultScalars);
0 commit comments