提交 0257ff1f 编写于 作者: D Don Syme 提交者: Kevin Ransom (msft)

Fix part of 3465 - allow nativeptr address in 'let x = &&expr' (#3525)

* Fix part of 3465 - allow nativeptr address of in 'let'

* fix tests

* fix test

* fix test
上级 e4c09f72
......@@ -624,7 +624,7 @@ and CheckExpr (cenv:cenv) (env:env) expr (context:ByrefContext) =
CheckExprsPermitByrefs cenv env rest
| Expr.Op (c,tyargs,args,m) ->
CheckExprOp cenv env (c,tyargs,args,m) context
CheckExprOp cenv env (c,tyargs,args,m) context expr
// Allow 'typeof<System.Void>' calls as a special case, the only accepted use of System.Void!
| TypeOfExpr cenv.g ty when isVoidTy cenv.g ty ->
......@@ -734,7 +734,7 @@ and CheckInterfaceImpls cenv env baseValOpt l =
and CheckInterfaceImpl cenv env baseValOpt (_ty,overrides) =
CheckMethods cenv env baseValOpt overrides
and CheckExprOp cenv env (op,tyargs,args,m) context =
and CheckExprOp cenv env (op,tyargs,args,m) context expr =
let limitedCheck() =
if env.limited then errorR(Error(FSComp.SR.chkObjCtorsCantUseExceptionHandling(), m))
List.iter (CheckTypePermitByrefs cenv env m) tyargs
......@@ -828,13 +828,13 @@ and CheckExprOp cenv env (op,tyargs,args,m) context =
CheckTypeInstNoByrefs cenv env m tyargs
| TOp.ValFieldGetAddr rfref,tyargs,[] ->
if noByrefs context && cenv.reportErrors then
if noByrefs context && cenv.reportErrors && isByrefLikeTy cenv.g (tyOfExpr cenv.g expr) then
errorR(Error(FSComp.SR.chkNoAddressStaticFieldAtThisPoint(rfref.FieldName), m))
CheckTypeInstNoByrefs cenv env m tyargs
// NOTE: there are no arg exprs to check in this case
| TOp.ValFieldGetAddr rfref,tyargs,[rx] ->
if noByrefs context && cenv.reportErrors then
if noByrefs context && cenv.reportErrors && isByrefLikeTy cenv.g (tyOfExpr cenv.g expr) then
errorR(Error(FSComp.SR.chkNoAddressFieldAtThisPoint(rfref.FieldName), m))
// This construct is used for &(rx.rfield) and &(rx->rfield). Relax to permit byref types for rx. [See Bug 1263].
CheckTypeInstNoByrefs cenv env m tyargs
......@@ -849,7 +849,7 @@ and CheckExprOp cenv env (op,tyargs,args,m) context =
CheckExprPermitByref cenv env arg1 // allow byref - it may be address-of-struct
| TOp.UnionCaseFieldGetAddr (uref, _idx),tyargs,[rx] ->
if noByrefs context && cenv.reportErrors then
if noByrefs context && cenv.reportErrors && isByrefLikeTy cenv.g (tyOfExpr cenv.g expr) then
errorR(Error(FSComp.SR.chkNoAddressFieldAtThisPoint(uref.CaseName), m))
CheckTypeInstNoByrefs cenv env m tyargs
// allow rx to be byref here, for struct unions
......@@ -870,12 +870,12 @@ and CheckExprOp cenv env (op,tyargs,args,m) context =
// permit byref for lhs lvalue of readonly value
CheckExprPermitByref cenv env lhs
| [ I_ldflda (fspec) | I_ldsflda (fspec) ],[lhs] ->
if noByrefs context && cenv.reportErrors then
if noByrefs context && cenv.reportErrors && isByrefLikeTy cenv.g (tyOfExpr cenv.g expr) then
errorR(Error(FSComp.SR.chkNoAddressFieldAtThisPoint(fspec.Name), m))
// permit byref for lhs lvalue
CheckExprPermitByref cenv env lhs
| [ I_ldelema (_,isNativePtr,_,_) ],lhsArray::indices ->
if not(isNativePtr) && noByrefs context && cenv.reportErrors then
if noByrefs context && cenv.reportErrors && not isNativePtr && isByrefLikeTy cenv.g (tyOfExpr cenv.g expr) then
errorR(Error(FSComp.SR.chkNoAddressOfArrayElementAtThisPoint(), m))
// permit byref for lhs lvalue
CheckExprPermitByref cenv env lhsArray
......@@ -982,7 +982,7 @@ and CheckLambdas isTop (memInfo: ValMemberInfo option) cenv env inlined topValIn
| _ ->
// Permit byrefs for let x = ...
CheckTypePermitByrefs cenv env m ety
if not inlined && isByrefLikeTy cenv.g ety then
if not inlined && (isByrefLikeTy cenv.g ety || isNativePtrTy cenv.g ety) then
// allow byref to occur as RHS of byref binding.
CheckExprPermitByref cenv env e
else
......
......@@ -1681,6 +1681,12 @@ module TypecheckTests =
peverify cfg "pos27.exe"
[<Test>]
let ``sigs pos28`` () =
let cfg = testConfig "typecheck/sigs"
fsc cfg "%s --target:exe -o:pos28.exe" cfg.fsc_flags ["pos28.fs"]
peverify cfg "pos28.exe"
[<Test>]
let ``sigs pos26`` () =
let cfg = testConfig "typecheck/sigs"
......
module Pos28
open FSharp.NativeInterop
module Test1 =
[<Struct>]
type Point =
val mutable X: int
val mutable Y: int
new(x,y) = { X=x; Y=y; }
let fixPoint1() =
let mutable point = Point(1,2)
let p1 = &&point.X
NativePtr.read<int> p1
module Test2 =
[<Struct>]
type Point = { mutable x : int; mutable y : int }
let fixPoint1() =
let mutable point = Unchecked.defaultof<Point>
let p1 = &&point.x
NativePtr.read<int> p1
// #Regression #Conformance #DataExpressions
// AddressOf Operator (warnings)
// Verify we can the compiler always issue warnings about using & and && operators
//<Expects status="warning" span="(9,11-9,14)" id="FS0051">The use of native pointers may result in unverifiable \.NET IL code$</Expects>
//<Expects status="error" span="(9,13-9,14)" id="FS0421">The address of the variable 'x' cannot be used at this point$</Expects>
module M =
let mutable x = 10
let w = &&x
......@@ -3,4 +3,3 @@ NoMT SOURCE=addressof001.fsx PRECMD="\$CSC_PIPE /t:library addressof001dll.cs"
NoMT SOURCE=addressof002.fsx PRECMD="\$CSC_PIPE /t:library addressof002dll.cs" # addressof002.fsx
NOMONO SOURCE=addressof003.fs SCFLAGS="--test:ErrorRanges" PRECMD="copy /y addressof003dll_%OSARCH%.dll addressof003dll.dll" PEVER=/MD # addressof003.fs
SOURCE=E_byrefvaluesnotpermitted001.fs SCFLAGS="--test:ErrorRanges" # E_byrefvaluesnotpermitted001.fs
SOURCE=E_byrefvaluesnotpermitted002.fs SCFLAGS="--test:ErrorRanges" # E_byrefvaluesnotpermitted002.fs
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册