| ... |
... |
@@ -328,37 +328,68 @@ dsFCall fn_id co fcall mDeclHeader = do |
|
328
|
328
|
toCName :: Id -> String
|
|
329
|
329
|
toCName i = showSDocOneLine defaultSDocContext (pprCode (ppr (idName i)))
|
|
330
|
330
|
|
|
|
331
|
+{- Note [Collapsing void pointer chains]
|
|
|
332
|
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
333
|
+When translating Haskell types like (Ptr (Ptr Abstract)) to C types for capi
|
|
|
334
|
+wrappers, where Abstract has no CType annotation, naively we would produce
|
|
|
335
|
+"void**". This is problematic because in C, only void* has implicit conversion
|
|
|
336
|
+to any pointer type.
|
|
|
337
|
+Modern compilers (gcc, clang) treat -Wincompatible-pointer-types as an error
|
|
|
338
|
+by default (#26852), causing compilation failures for capi wrappers.
|
|
|
339
|
+
|
|
|
340
|
+The fix is to collapse void pointer chains: whenever the inner type of a
|
|
|
341
|
+Ptr/FunPtr resolves to void (i.e. the Haskell type has no known C
|
|
|
342
|
+representation), we return void* instead of void**, void***, etc.
|
|
|
343
|
+This works because void* implicitly converts to any pointer type in C.
|
|
|
344
|
+
|
|
|
345
|
+Examples:
|
|
|
346
|
+ Ptr Abstract => void*
|
|
|
347
|
+ Ptr (Ptr Abstract) => void* (used to be void**)
|
|
|
348
|
+ Ptr (Ptr (Ptr Abstract)) => void*
|
|
|
349
|
+ Ptr (Ptr CInt) => int** (CInt has CType "int", don't collapse)
|
|
|
350
|
+-}
|
|
|
351
|
+
|
|
|
352
|
+-- | See Note [Collapsing void pointer chains]
|
|
331
|
353
|
toCType :: Type -> (Maybe (Header GhcTc), SDoc)
|
|
332
|
|
-toCType = f False
|
|
333
|
|
- where f voidOK t
|
|
334
|
|
- -- First, if we have (Ptr t) of (FunPtr t), then we need to
|
|
|
354
|
+toCType t = case f False t of
|
|
|
355
|
+ (mh, _, cType) -> (mh, cType)
|
|
|
356
|
+ where
|
|
|
357
|
+ -- The Bool in the return type indicates whether the C type is
|
|
|
358
|
+ -- "void" due to an unknown Haskell type (True = void-based).
|
|
|
359
|
+ f :: Bool -> Type -> (Maybe (Header GhcTc), Bool, SDoc)
|
|
|
360
|
+ f voidOK t
|
|
|
361
|
+ -- First, if we have (Ptr t) or (FunPtr t), then we need to
|
|
335
|
362
|
-- convert t to a C type and put a * after it. If we don't
|
|
336
|
363
|
-- know a type for t, then "void" is fine, though.
|
|
|
364
|
+ -- If the inner type is void-based, we collapse the pointer
|
|
|
365
|
+ -- chain to just "void*". See Note [Collapsing void pointer chains].
|
|
337
|
366
|
| Just (ptr, [t']) <- splitTyConApp_maybe t
|
|
338
|
367
|
, tyConName ptr `elem` [ptrTyConName, funPtrTyConName]
|
|
339
|
368
|
= case f True t' of
|
|
340
|
|
- (mh, cType') ->
|
|
341
|
|
- (mh, cType' <> char '*')
|
|
|
369
|
+ (mh, True, _) ->
|
|
|
370
|
+ (mh, True, text "void*")
|
|
|
371
|
+ (mh, False, cType') ->
|
|
|
372
|
+ (mh, False, cType' <> char '*')
|
|
342
|
373
|
-- Otherwise, if we have a type constructor application, then
|
|
343
|
374
|
-- see if there is a C type associated with that constructor.
|
|
344
|
375
|
-- Note that we aren't looking through type synonyms or
|
|
345
|
376
|
-- anything, as it may be the synonym that is annotated.
|
|
346
|
377
|
| Just tycon <- tyConAppTyConPicky_maybe t
|
|
347
|
378
|
, Just (CType _ mHeader cType) <- tyConCType_maybe tycon
|
|
348
|
|
- = (mHeader, ftext cType)
|
|
|
379
|
+ = (mHeader, False, ftext cType)
|
|
349
|
380
|
-- If we don't know a C type for this type, then try looking
|
|
350
|
381
|
-- through one layer of type synonym etc.
|
|
351
|
382
|
| Just t' <- coreView t
|
|
352
|
383
|
= f voidOK t'
|
|
353
|
|
- -- Handle 'UnliftedFFITypes' argument
|
|
|
384
|
+ -- Handle 'UnliftedFFITypes' argument
|
|
354
|
385
|
| Just tyCon <- tyConAppTyConPicky_maybe t
|
|
355
|
386
|
, isPrimTyCon tyCon
|
|
356
|
387
|
, Just cType <- ppPrimTyConStgType tyCon
|
|
357
|
|
- = (Nothing, text cType)
|
|
|
388
|
+ = (Nothing, False, text cType)
|
|
358
|
389
|
|
|
359
|
390
|
-- Otherwise we don't know the C type. If we are allowing
|
|
360
|
391
|
-- void then return that; otherwise something has gone wrong.
|
|
361
|
|
- | voidOK = (Nothing, text "void")
|
|
|
392
|
+ | voidOK = (Nothing, True, text "void")
|
|
362
|
393
|
| otherwise
|
|
363
|
394
|
= pprPanic "toCType" (ppr t)
|
|
364
|
395
|
|