- tcHsType hs_ty `thenTc` \ ty ->
- -- Check that the type has the right shape
- -- and that the argument and result types are acceptable.
- let
- -- drop the foralls before inspecting the structure
- -- of the foreign type.
- (_, t_ty) = splitForAllTys ty
- in
- case splitFunTys t_ty of
- (arg_tys, res_ty) ->
- checkForeignImport (isDynamic ext_nm) ty arg_tys res_ty `thenTc_`
- let i = (mkUserId nm ty) in
- returnTc (i, (ForeignDecl i imp_exp undefined ext_nm cconv src_loc))
+------------ Checking types for foreign import ----------------------
+\begin{code}
+tcCheckFIType _ arg_tys res_ty (DNImport spec)
+ = checkCg checkDotnet `thenM_`
+ getDOpts `thenM` \ dflags ->
+ checkForeignArgs (isFFIDotnetTy dflags) arg_tys `thenM_`
+ checkForeignRes True{-non IO ok-} (isFFIDotnetTy dflags) res_ty `thenM_`
+ let (DNCallSpec isStatic kind _ _ _ _) = spec in
+ (case kind of
+ DNMethod | not isStatic ->
+ case arg_tys of
+ [] -> addErrTc illegalDNMethodSig
+ _
+ | not (isFFIDotnetObjTy (last arg_tys)) -> addErrTc illegalDNMethodSig
+ | otherwise -> returnM ()
+ _ -> returnM ()) `thenM_`
+ returnM (DNImport (withDNTypes spec (map toDNType arg_tys) (toDNType res_ty)))
+
+tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport _ _ _ _ (CLabel _))
+ = checkCg checkCOrAsm `thenM_`
+ check (isFFILabelTy sig_ty) (illegalForeignTyErr empty sig_ty) `thenM_`
+ return idecl
+
+tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv _ _ _ CWrapper)
+ = -- Foreign wrapper (former f.e.d.)
+ -- The type must be of the form ft -> IO (FunPtr ft), where ft is a
+ -- valid foreign type. For legacy reasons ft -> IO (Ptr ft) as well
+ -- as ft -> IO Addr is accepted, too. The use of the latter two forms
+ -- is DEPRECATED, though.
+ checkCg checkCOrAsmOrInterp `thenM_`
+ (case arg_tys of
+ [arg1_ty] -> checkForeignArgs isFFIExternalTy arg1_tys `thenM_`
+ checkForeignRes nonIOok isFFIExportResultTy res1_ty `thenM_`
+ checkForeignRes mustBeIO isFFIDynResultTy res_ty `thenM_`
+ checkFEDArgs arg1_tys
+ where
+ (arg1_tys, res1_ty) = tcSplitFunTys arg1_ty
+ other -> addErrTc (illegalForeignTyErr empty sig_ty) ) `thenM_`
+ return idecl
+
+tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport _ safety _ _ (CFunction target))
+ | isDynamicTarget target -- Foreign import dynamic
+ = checkCg checkCOrAsmOrInterp `thenM_`
+ case arg_tys of -- The first arg must be Ptr, FunPtr, or Addr
+ [] ->
+ check False (illegalForeignTyErr empty sig_ty) `thenM_`
+ return idecl
+ (arg1_ty:arg_tys) ->
+ getDOpts `thenM` \ dflags ->
+ check (isFFIDynArgumentTy arg1_ty)
+ (illegalForeignTyErr argument arg1_ty) `thenM_`
+ checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys `thenM_`
+ checkForeignRes nonIOok (isFFIImportResultTy dflags) res_ty `thenM_`
+ return idecl
+ | otherwise -- Normal foreign import
+ = checkCg (if isCasmTarget target
+ then checkC else checkCOrAsmOrDotNetOrInterp) `thenM_`
+ checkCTarget target `thenM_`
+ getDOpts `thenM` \ dflags ->
+ checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys `thenM_`
+ checkForeignRes nonIOok (isFFIImportResultTy dflags) res_ty `thenM_`
+ return idecl
+
+-- This makes a convenient place to check
+-- that the C identifier is valid for C
+checkCTarget (StaticTarget str)
+ = checkCg checkCOrAsmOrDotNetOrInterp `thenM_`
+ check (isCLabelString str) (badCName str)
+
+checkCTarget (CasmTarget _)
+ = checkCg checkC
+\end{code}