@@ -297,24 +297,45 @@ let get_local_attribute l =
297
297
let attr = find_attribute is_local_attribute l in
298
298
parse_local_attribute attr
299
299
300
- let get_property_attribute l p =
300
+ let get_property_attribute l p ~ fun_attr =
301
301
let attr = find_attribute (is_property_attribute p) l in
302
302
let res = parse_property_attribute attr p in
303
303
(match attr, res with
304
304
| None , Default_check -> ()
305
305
| _ , Default_check -> ()
306
306
| None , (Check _ | Ignore_assert_all _ ) -> assert false
307
307
| Some _ , Ignore_assert_all _ -> ()
308
- | Some attr , Check _ ->
308
+ | Some attr , Check { assume; _ } ->
309
309
if ! Clflags. zero_alloc_check && ! Clflags. native_code then
310
310
(* The warning for unchecked functions will not trigger if the check is requested
311
311
through the [@@@zero_alloc all] top-level annotation rather than through the
312
312
function annotation [@zero_alloc]. *)
313
- Builtin_attributes. register_property attr.attr_name);
313
+ if assume then begin
314
+ (* [attr.inline] and [attr.specialise] must be set before the
315
+ check for [Warnings.Misplaced_assume_attribute].
316
+ For attributes from the same list, it's fine because
317
+ [add_check_attribute] is called after
318
+ [add_inline_attribute] and [add_specialise_attribute].
319
+ The warning will spuriously fire in the following case:
320
+ let[@inline never][@specialise never] f =
321
+ fun[@zero_alloc assume] x -> ..
322
+ *)
323
+ let never_specialise =
324
+ if Config. flambda then
325
+ fun_attr.specialise = Never_specialise
326
+ else
327
+ (* closure drops [@specialise never] and never specialises *)
328
+ (* flambda2 does not have specialisation support yet *)
329
+ true
330
+ in
331
+ if not ((fun_attr.inline = Never_inline ) && never_specialise) then
332
+ Location. prerr_warning attr.attr_name.loc
333
+ (Warnings. Misplaced_assume_attribute attr.attr_name.txt)
334
+ end
335
+ else
336
+ Builtin_attributes. register_property attr.attr_name);
314
337
res
315
338
316
- let get_check_attribute l = get_property_attribute l Zero_alloc
317
-
318
339
let get_poll_attribute l =
319
340
let attr = find_attribute is_poll_attribute l in
320
341
parse_poll_attribute attr
@@ -425,7 +446,7 @@ let add_check_attribute expr loc attributes =
425
446
in
426
447
match expr with
427
448
| Lfunction ({ attr = { stub = false } as attr ; } as funct ) ->
428
- begin match get_check_attribute attributes with
449
+ begin match get_property_attribute attributes Zero_alloc ~fun_attr: attr with
429
450
| Default_check -> expr
430
451
| (Ignore_assert_all p | Check { property = p ; _ } ) as check ->
431
452
begin match attr.check with
0 commit comments