···180180 "In object types, attaching attributes to inherited \
181181 subtypes is not allowed."
182182 in
183183+ let attribute self attr =
184184+ (* The change to `self` here avoids registering attributes within attributes
185185+ for the purposes of warning 53, while keeping all the other invariant
186186+ checks for attribute payloads. See comment on [attr_tracking_time] in
187187+ [builtin_attributes.mli]. *)
188188+ super.attribute { self with attribute = super.attribute } attr;
189189+ Builtin_attributes.(register_attr Invariant_check attr.attr_name)
190190+ in
183191 { super with
184192 type_declaration
185193 ; typ
···195203 ; signature_item
196204 ; row_field
197205 ; object_field
206206+ ; attribute
198207 }
199208200209let structure st = iterator.structure iterator st
+76
parsing/builtin_attributes.ml
···15151616open Asttypes
1717open Parsetree
1818+open Ast_helper
1919+2020+2121+module Attribute_table = Hashtbl.Make (struct
2222+ type t = string with_loc
2323+2424+ let hash : t -> int = Hashtbl.hash
2525+ let equal : t -> t -> bool = (=)
2626+end)
2727+let unused_attrs = Attribute_table.create 128
2828+let mark_used t = Attribute_table.remove unused_attrs t
2929+3030+(* [attr_order] is used to issue unused attribute warnings in the order the
3131+ attributes occur in the file rather than the random order of the hash table
3232+*)
3333+let attr_order a1 a2 =
3434+ match String.compare a1.loc.loc_start.pos_fname a2.loc.loc_start.pos_fname
3535+ with
3636+ | 0 -> Int.compare a1.loc.loc_start.pos_cnum a2.loc.loc_start.pos_cnum
3737+ | n -> n
3838+3939+let warn_unused () =
4040+ let keys = List.of_seq (Attribute_table.to_seq_keys unused_attrs) in
4141+ let keys = List.sort attr_order keys in
4242+ List.iter (fun sloc ->
4343+ Location.prerr_warning sloc.loc (Warnings.Misplaced_attribute sloc.txt))
4444+ keys
4545+4646+(* These are the attributes that are tracked in the builtin_attrs table for
4747+ misplaced attribute warnings. *)
4848+let builtin_attrs =
4949+ [ (* "alert"; "ocaml.alert" *)
5050+ (* ; "boxed"; "ocaml.boxed" *)
5151+ (* ; "deprecated"; "ocaml.deprecated" *)
5252+ (* ; "deprecated_mutable"; "ocaml.deprecated_mutable" *)
5353+ (* ; "explicit_arity"; "ocaml.explicit_arity" *)
5454+ (* ; "immediate"; "ocaml.immediate" *)
5555+ (* ; "immediate64"; "ocaml.immediate64" *)
5656+ (* ; "inline"; "ocaml.inline" *)
5757+ (* ; "inlined"; "ocaml.inlined" *)
5858+ (* ; "noalloc"; "ocaml.noalloc" *)
5959+ (* ; "ppwarning"; "ocaml.ppwarning" *)
6060+ (* ; "tailcall"; "ocaml.tailcall" *)
6161+ (* ; "unboxed"; "ocaml.unboxed" *)
6262+ (* ; "untagged"; "ocaml.untagged" *)
6363+ (* ; "unrolled"; "ocaml.unrolled" *)
6464+ (* ; "warnerror"; "ocaml.warnerror" *)
6565+ (* ; "warning"; "ocaml.warning" *)
6666+ (* ; "warn_on_literal_pattern"; "ocaml.warn_on_literal_pattern" *)
6767+ ]
6868+6969+let builtin_attrs =
7070+ let tbl = Hashtbl.create 128 in
7171+ List.iter (fun attr -> Hashtbl.add tbl attr ()) builtin_attrs;
7272+ tbl
7373+7474+let is_builtin_attr s = Hashtbl.mem builtin_attrs s
7575+7676+type attr_tracking_time = Parser | Invariant_check
7777+7878+let register_attr attr_tracking_time name =
7979+ match attr_tracking_time with
8080+ | Parser when !Clflags.all_ppx <> [] -> ()
8181+ | Parser | Invariant_check ->
8282+ if is_builtin_attr name.txt then
8383+ Attribute_table.replace unused_attrs name ()
18841985let string_of_cst = function
2086 | Pconst_string(s, _, _) -> Some s
···66132 end
67133 | ({txt; loc}, _) ->
68134 Location.errorf ~loc "Uninterpreted extension '%s'." txt
135135+136136+let mark_payload_attrs_used payload =
137137+ let iter =
138138+ { Ast_iterator.default_iterator
139139+ with attribute = fun self a ->
140140+ mark_used a.attr_name;
141141+ Ast_iterator.default_iterator.attribute self a
142142+ }
143143+ in
144144+ iter.payload iter payload
6914570146let kind_and_message = function
71147 | PStr[
+48-9
parsing/builtin_attributes.mli
···1313(* *)
1414(**************************************************************************)
15151616-(** Support for some of the builtin attributes
1616+(** Support for the builtin attributes:
17171818+ - ocaml.alert
1919+ - ocaml.boxed
1820 - ocaml.deprecated
1919- - ocaml.alert
2020- - ocaml.error
2121+ - ocaml.deprecated_mutable
2222+ - ocaml.explicit_arity
2323+ - ocaml.immediate
2424+ - ocaml.immediate64
2525+ - ocaml.inline
2626+ - ocaml.inlined
2727+ - ocaml.noalloc
2128 - ocaml.ppwarning
2222- - ocaml.warning
2929+ - ocaml.tailcall
3030+ - ocaml.unboxed
3131+ - ocaml.untagged
3232+ - ocaml.unrolled
2333 - ocaml.warnerror
2424- - ocaml.explicit_arity (for camlp4/camlp5)
3434+ - ocaml.warning
2535 - ocaml.warn_on_literal_pattern
2626- - ocaml.deprecated_mutable
2727- - ocaml.immediate
2828- - ocaml.immediate64
2929- - ocaml.boxed / ocaml.unboxed
30363137 {b Warning:} this module is unstable and part of
3238 {{!Compiler_libs}compiler-libs}.
33393440*)
4141+4242+4343+(** [register_attr] must be called on the locations of all attributes that
4444+ should be tracked for the purpose of misplaced attribute warnings. In
4545+ particular, it should be called on all attributes that are present in the
4646+ source program except those that are contained in the payload of another
4747+ attribute (because these may be left behind by a ppx and intentionally
4848+ ignored by the compiler).
4949+5050+ The [attr_tracking_time] argument indicates when the attr is being added for
5151+ tracking - either when it is created in the parser or when we see it while
5252+ running the check in the [Ast_invariants] module. This ensures that we
5353+ track only attributes from the final version of the parse tree: we skip
5454+ adding attributes at parse time if we can see that a ppx will be run later,
5555+ because the [Ast_invariants] check is always run on the result of a ppx.
5656+5757+ Note that the [Ast_invariants] check is also run on parse trees created from
5858+ marshalled ast files if no ppx is being used, ensuring we don't miss
5959+ attributes in that case.
6060+*)
6161+type attr_tracking_time = Parser | Invariant_check
6262+val register_attr : attr_tracking_time -> string Location.loc -> unit
6363+6464+(** Marks the attributes hiding in the payload of another attribute used, for
6565+ the purposes of misplaced attribute warnings (see comment on
6666+ [attr_tracking_time] above). In the parser, it's simplest to add these to
6767+ the table and remove them later, rather than threading through state
6868+ tracking whether we're in an attribute payload. *)
6969+val mark_payload_attrs_used : Parsetree.payload -> unit
7070+7171+(** Issue misplaced attribute warnings for all attributes created with
7272+ [mk_internal] but not yet marked used. *)
7373+val warn_unused : unit -> unit
35743675val check_alerts: Location.t -> Parsetree.attributes -> string -> unit
3776val check_alerts_inclusion: