### Set up OCaml Switch Source: https://github.com/antique-team/clangml/blob/master/doc/clang38_to_clang39.txt Ensure OCaml v4.03.0 is installed and configured as a non-system switch using OPAM. ```bash opam switch 4.03.0 eval `opam config env` ``` -------------------------------- ### Install Clang and Dependencies (Debian/Ubuntu) Source: https://github.com/antique-team/clangml/blob/master/doc/clang-upgrade-howto.txt Installs a specific Clang version (e.g., 3.6) and its associated libraries on Debian/Ubuntu systems. Ensure you have the correct version number for your needs. ```bash sudo apt-get install \ clang-3.6 libclang-3.6-dev llvm-3.6-dev binutils-dev libboost-dev ``` -------------------------------- ### Compile and Test MemCAD with Clangml Source: https://github.com/antique-team/clangml/blob/master/doc/clang38_to_clang39.txt Download, compile, and run the regression test suite for MemCAD using the current Clangml setup. ```bash cd ~/src wget https://github.com/Antique-team/memcad/archive/v1.0.0.tar.gz tar xzf v1.0.0.tar.gz cd memcad-1.0.0 opam pin -n add memcad $PWD make # launch the regression test suite make prtp ``` -------------------------------- ### Install Clangml for Clang 3.8.0 Source: https://github.com/antique-team/clangml/blob/master/doc/clang38_to_clang39.txt Clone the Clangml repository, checkout the branch for Clang 3.8.0, pin it, remove and then reinstall it with dependencies. ```bash cd ~/src git clone https://github.com/Antique-team/clangml.git cd clangml git checkout clang_3.8 # branch for clang-3.8.0 opam pin -n add clangml $PWD opam remove clangml opam depext -i clangml # install all dependencies ``` -------------------------------- ### Iterate and fold over AST with Clang.Visitor Source: https://context7.com/antique-team/clangml/llms.txt Implement custom AST traversal logic by overriding hooks in `FoldVisitor`. This example counts integer literals in a translation unit. Requires `Clang.Api` and `Clang.Ast` to be opened. ```ocaml open Clang.Api open Clang.Ast (* Count all integer literals in a translation unit *) let count_integer_literals clang = let tu = request clang TranslationUnit in (* Build a fold visitor that intercepts expr nodes *) let fold_expr v count expr = let count = match expr.e with | IntegerLiteral _ -> count + 1 | _ -> count in (* recurse into children *) FoldVisitor.visit_expr v count expr in let v = FoldVisitor.({ default with fold_expr }) in FoldVisitor.visit_decl v 0 tu let () = parse ["code.c"] (fun clang -> let n = count_integer_literals clang in Printf.printf "Integer literals found: %d\n" n ) ``` -------------------------------- ### Clang.Analysis.NamingConvention.analyse_decl Source: https://context7.com/antique-team/clangml/llms.txt Checks C reserved-name violations in declarations. It identifies names that start with `__` or `_` followed by an uppercase letter, which are reserved by the C standard. Diagnostics are printed with ANSI color coding. ```APIDOC ## `Clang.Analysis.NamingConvention.analyse_decl` — Check C reserved-name violations Walks all declarations in a translation unit and emits diagnostics for names that begin with `__` or `_` followed by an uppercase letter, which are reserved by the C standard (ISO C99 §7.1.3). Diagnostics are printed with ANSI colour coding via `Clang.Diagnostic.show`. ```ocaml open Clang.Api open Clang.Analysis let () = parse ["-std=c99"; "user_code.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | Clang.Ast.TranslationUnitDecl decls -> (* Filter to user-defined declarations before checking *) let user_decls = List.filter (fun d -> Clang.Sloc.is_valid d.Clang.Ast.d_sloc.Clang.Ast.loc_s && request clang (FileCharacteristic d.Clang.Ast.d_sloc.Clang.Ast.loc_s) = Clang.Sloc.C_User ) decls in List.iter (fun d -> NamingConvention.analyse_decl clang d) user_decls | _ -> () ) (* For a file containing: int __bad_name = 1; int _Bad_name = 2; int good_name = 3; Prints to stderr (with ANSI colour): user_code.c:1:5: warning: reserved variable name `__bad_name' [-Wreserved-name, ISO C99 §7.1.3] user_code.c:2:5: warning: reserved variable name `_Bad_name' [-Wreserved-name, ISO C99 §7.1.3] *) ``` ``` -------------------------------- ### Consumer entry-point pattern Source: https://context7.com/antique-team/clangml/llms.txt Demonstrates the canonical pattern for writing a clangml consumer. This involves opening Clang.Api and Clang.Ast, calling parse with command-line arguments, issuing a Compose request for filename and TU, and using Clang.Pp for output. ```APIDOC ## Consumer entry-point pattern — Full end-to-end processor The `consumer/processor.ml` file demonstrates the canonical pattern for writing a clangml consumer: open `Clang.Api` and `Clang.Ast`, call `parse` with command-line arguments, issue a `Compose` request to fetch the filename and TU in a single round-trip, and then use `Clang.Pp` for output. ```ocaml (* consumer/processor.ml — canonical clangml consumer *) open Clang.Api open Clang.Ast let process clang = (* Compose two requests into one round-trip for efficiency *) let file, decl = request clang @@ Compose (Filename, TranslationUnit) in Printf.printf "%% processing file %s\n" file; (* Pretty-print the full CST *) print_string "----- Clang CST -----\n"; Format.printf "@[@,%a@]@." Clang.Pp.pp_decl decl; (* Dump the raw Show string (useful for debugging) *) Printf.printf "----- gory details -----\n%s\n" (Clang.Pp.string_of_decl_ decl.d |> Str.global_replace (Str.regexp "^[ \t]+") "") let main () = Log.set_log_level Log.INFO; Printexc.record_backtrace true; (try (* Pass all argv elements after argv.(0) directly to clang *) Clang.Api.parse (List.tl @@ Array.to_list Sys.argv) process with Clang.Api.E error -> failwith @@ Clang.Api.string_of_error error) let () = main () (* Usage: ./processor my_file.c -I/usr/include -std=c99 *) ``` ``` -------------------------------- ### Prepare OPAM Repository for New Release Source: https://github.com/antique-team/clangml/blob/master/doc/RELEASE.txt Clone the OPAM repository, copy the existing ClangML package directory to a new version, and update the URL and MD5 in the `url` file. Ensure the `opam` file reflects any changes in external dependencies, such as the Clang version. ```bash git clone https://github.com/ocaml/opam-repository.git cd opam-repository cp -a packages/clangml/clangml.3.6.0.4 packages/clangml/clangml.3.6.0.5 ``` -------------------------------- ### Simple Clangml Test Source: https://github.com/antique-team/clangml/blob/master/doc/clang38_to_clang39.txt Compile a basic C file and process it with Clangml to verify the AST output. ```bash make echo 'int main() { return 0; }' > test.c ./processor.native test.c ``` -------------------------------- ### Canonical clangml consumer pattern Source: https://context7.com/antique-team/clangml/llms.txt Demonstrates the standard pattern for writing a clangml consumer, including efficient request composition and pretty-printing. ```ocaml (* consumer/processor.ml — canonical clangml consumer *) open Clang.Api open Clang.Ast let process clang = (* Compose two requests into one round-trip for efficiency *) let file, decl = request clang @@ Compose (Filename, TranslationUnit) in Printf.printf "%% processing file %s\n" file; (* Pretty-print the full CST *) print_string "----- Clang CST -----\n"; Format.printf "@[@,%a@]@." Clang.Pp.pp_decl decl; (* Dump the raw Show string (useful for debugging) *) Printf.printf "----- gory details -----\n%s\n" (Clang.Pp.string_of_decl_ decl.d |> Str.global_replace (Str.regexp "^[ \t]+") "") let main () = Log.set_log_level Log.INFO; Printexc.record_backtrace true; (try (* Pass all argv elements after argv.(0) directly to clang *) Clang.Api.parse (List.tl @@ Array.to_list Sys.argv) process with Clang.Api.E error -> failwith @@ Clang.Api.string_of_error error) let () = main () (* Usage: ./processor my_file.c -I/usr/include -std=c99 *) ``` -------------------------------- ### Compose Clang.Api.request queries for file info and type details Source: https://context7.com/antique-team/clangml/llms.txt Demonstrates composing multiple requests into a single round-trip to the Clang plugin. This snippet shows how to retrieve the filename and translation unit, query the size and alignment of a type, and check if a declaration originates from the main file. ```ocaml open Clang.Api open Clang.Ast let () = parse ["example.c"] (fun clang -> (* Compose two requests into a single round-trip *) let (filename, tu) : string * decl = request clang (Compose (Filename, TranslationUnit)) in Printf.printf "Parsing: %s\n" filename; (* Query size/alignment of a type via a ctyp Ref.t *) (* (assuming we already have a ctyp ref `ty_ref` from traversal) *) (match tu.d with | TranslationUnitDecl (first :: _) -> (match first.d with | VarDecl (tloc, name, _) -> let ty_ref = tloc.tl_type.t_cref in let sz : int64 = request clang (SizeofType ty_ref) in let aln : int = request clang (AlignofType ty_ref) in Printf.printf "Variable '%s': sizeof=%Ld alignof=%d\n" name sz aln | _ -> ()) | _ -> ()); (* Ask whether the first declaration's location is in the main file *) (match tu.d with | TranslationUnitDecl (d :: _) -> let in_main : bool = request clang (IsFromMainFile d.d_sloc.loc_s) in Printf.printf "First decl is from main file: %b\n" in_main | _ -> ()) ) ``` -------------------------------- ### Pretty-print AST nodes with Clang.Pp Source: https://context7.com/antique-team/clangml/llms.txt Use `pp_decl` and `string_of_decl_` for pretty-printing AST nodes. `pp_decl` outputs formatted strings, while `string_of_decl_` provides a compact, raw representation. Ensure `Clang.Api` and `Clang.Pp` are opened. ```ocaml open Clang.Api open Clang.Pp let () = parse ["example.c"] (fun clang -> let tu = request clang TranslationUnit in (* Pretty-print the entire translation unit to stdout *) Format.printf "@[@,%a@]@." pp_decl tu; (* Get a compact Show-derived string of the raw variant *) (match tu.d with | Clang.Ast.TranslationUnitDecl (first :: _) -> let raw = string_of_decl_ first.Clang.Ast.d in (* strip leading whitespace for readability *) let clean = Str.global_replace (Str.regexp "^[ ]+") "" raw in Printf.printf "--- raw show ---\n%s\n" clean | _ -> ()) ``` -------------------------------- ### Tag a New ClangML Release Source: https://github.com/antique-team/clangml/blob/master/doc/RELEASE.txt Tag the new software version using Git and push the tags to the remote repository. Follow the versioning scheme that supports a specific Clang version. ```bash git tag v3.6.0.5 # for example git push --tags git@github.com:Antique-team/clangml.git ``` -------------------------------- ### Clang.Api.parse Source: https://context7.com/antique-team/clangml/llms.txt Parses a source file using a Clang subprocess and returns its Abstract Syntax Tree (AST). It takes a list of arguments to be passed to Clang and a continuation function that receives a Clang handle for further AST queries. ```APIDOC ## `Clang.Api.parse` — Parse a source file and receive its AST Spawns a `clang-3.9` subprocess with the clangml plugin loaded, performs a version handshake, and then passes a `clang` handle to the user-supplied continuation. All subsequent AST queries are issued through that handle. The `args` list is forwarded verbatim to Clang (file paths, `-I` flags, `-std=` flags, etc.). ```ocaml (* Parse a single C file and print its translation-unit declaration *) open Clang.Api open Clang.Ast let () = (* "args" are passed directly to clang-3.9 *) parse ["test.c"] (fun clang -> (* Request the top-level TranslationUnit decl node *) let tu : decl = request clang TranslationUnit in match tu.d with | TranslationUnitDecl decls -> Printf.printf "Found %d top-level declarations\n" (List.length decls); List.iter (fun d -> match d.d with | FunctionDecl (_, DN_Identifier name, _) -> Printf.printf " function: %s\n" name | VarDecl (_, name, _) -> Printf.printf " variable: %s\n" name | TypedefDecl (_, name) -> Printf.printf " typedef: %s\n" name | _ -> () ) decls | _ -> failwith "unexpected root node" ) (* Expected output for a file containing: typedef int my_int; int global_var = 42; int foo(int x) { return x + 1; } Found 3 top-level declarations typedef: my_int variable: global_var function: foo *) ``` ``` -------------------------------- ### View Git Diff for ClangML Version Comparison Source: https://github.com/antique-team/clangml/blob/master/doc/clang-upgrade-howto.txt Compares the ClangML code for two different Clang versions using Git. This is useful for understanding the changes introduced during an upgrade. ```bash https://github.com/Antique-team/clangml/compare/clang_3.4...clang_update_3.5 ``` -------------------------------- ### Access AST information with Clang.Query Source: https://context7.com/antique-team/clangml/llms.txt Utilize `Clang.Query` for common AST traversal patterns, such as extracting function return types and arguments, or inspecting record fields. Requires `Clang.Query` and `Clang.Ast` to be opened. ```ocaml open Clang.Query open Clang.Ast let summarise_function (d : decl) = match d.d with | FunctionDecl (fd_type, DN_Identifier name, body_opt) -> let ret_tloc = return_type_of_tloc fd_type.tl in let arg_decls = args_of_tloc fd_type.tl in Printf.printf "function %s: %d params\n" name (List.length arg_decls); (* Flatten a body into a list of statements *) (match body_opt with | Some body -> let stmts = body_of_stmt body in Printf.printf " body has %d statements\n" (List.length stmts) | None -> Printf.printf " (declaration only)\n"); (* Check whether the return type is volatile-qualified *) if is_volatile_tloc ret_tloc.tl then Printf.printf " return type is volatile\n" | RecordDecl (_, name, _, _) -> let fields = fields_of_record_decl d.d in Printf.printf "struct %s has %d fields\n" name (List.length fields) | TypedefDecl _ -> let underlying = underlying_type_of_typedef_decl d.d in Printf.printf " underlying type loc: %s\n" (Clang.Pp.string_of_tloc_ underlying.tl) | _ -> () ``` -------------------------------- ### Commit New OPAM Package Version Source: https://github.com/antique-team/clangml/blob/master/doc/RELEASE.txt Create a new Git branch for the specific package version, add the new package directory to staging, and commit the changes to the OPAM repository. ```bash git checkout -b clangml_3.6.0.5 git add packages/clangml/clangml.3.6.0.5 git commit packages/clangml/clangml.3.6.0.5 ``` -------------------------------- ### Parse C file and print top-level declarations using Clang.Api.parse Source: https://context7.com/antique-team/clangml/llms.txt Spawns a clang-3.9 subprocess to parse a C file and retrieves the translation-unit declaration. The 'args' list is forwarded directly to clang. This snippet demonstrates iterating over top-level declarations and identifying functions, variables, and typedefs. ```ocaml (* Parse a single C file and print its translation-unit declaration *) open Clang.Api open Clang.Ast let () = (* "args" are passed directly to clang-3.9 *) parse ["test.c"] (fun clang -> (* Request the top-level TranslationUnit decl node *) let tu : decl = request clang TranslationUnit in match tu.d with | TranslationUnitDecl decls -> Printf.printf "Found %d top-level declarations\n" (List.length decls); List.iter (fun d -> match d.d with | FunctionDecl (_, DN_Identifier name, _) -> Printf.printf " function: %s\n" name | VarDecl (_, name, _) -> Printf.printf " variable: %s\n" name | TypedefDecl (_, name) -> Printf.printf " typedef: %s\n" name | _ -> () ) decls | _ -> failwith "unexpected root node" ) (* Expected output for a file containing: typedef int my_int; int global_var = 42; int foo(int x) { return x + 1; } Found 3 top-level declarations typedef: my_int variable: global_var function: foo *) ``` -------------------------------- ### Clang.Api.request with FileCharacteristic Source: https://context7.com/antique-team/clangml/llms.txt Determines if a location is user code or a system header, returning `Sloc.C_User`, `Sloc.C_System`, or `Sloc.C_ExternCSystem`. This helps tools skip declarations from system headers. ```APIDOC ## `Clang.Api.request` with `FileCharacteristic` — Determine if a location is user code or a system header Returns `Sloc.C_User`, `Sloc.C_System`, or `Sloc.C_ExternCSystem` for a given source location, enabling tools to skip declarations that originate from system headers. ```ocaml open Clang.Api open Clang.Sloc let is_user_code clang (sloc : Clang.Ast.sloc) = if Sloc.is_valid sloc.Clang.Ast.loc_s then request clang (FileCharacteristic sloc.Clang.Ast.loc_s) = C_User else false let () = parse ["-std=c99"; "input.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | Clang.Ast.TranslationUnitDecl decls -> let user_decls = List.filter (fun d -> is_user_code clang d.Clang.Ast.d_sloc) decls in Printf.printf "%d user-defined declarations\n" (List.length user_decls) | _ -> () ) ``` ``` -------------------------------- ### Emit structured diagnostic with ANSI colour using Clang.Diagnostic.show Source: https://context7.com/antique-team/clangml/llms.txt Resolves Sloc.t to a location and prints a GCC-style diagnostic line with ANSI colour codes. Use for custom warnings or errors. ```ocaml open Clang.Api open Clang.Diagnostic open Clang.Sloc let emit_warning clang (sloc : Clang.Ast.sloc) message = let diag = { diag_loc = sloc.Clang.Ast.loc_s; diag_msg = message; diag_std = Std_C "6.5.3.2"; diag_flg = Wreserved_name; diag_lvl = Warning; } in show clang diag let () = parse ["target.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | Clang.Ast.TranslationUnitDecl (d :: _) -> emit_warning clang d.Clang.Ast.d_sloc "example diagnostic from OCaml analysis" | _ -> () ) (* Output to stderr (with ANSI bold/colour): target.c:1:1: warning: example diagnostic from OCaml analysis [-Wreserved-name, ISO C99 §6.5.3.2] *) ``` -------------------------------- ### Retrieve Complete Type Cache with CacheFor Source: https://context7.com/antique-team/clangml/llms.txt Retrieves a `DenseIntMap` containing all `ctyp` values created during the session, indexed by `t_self`. This allows efficient iteration over all types encountered without re-traversing the AST. Ensure the Translation Unit is fetched first to populate the cache. ```ocaml open Clang.Api open Clang.Ast let () = parse ["big_file.c"] (fun clang -> (* First fetch the TU so the cache is populated *) let _ = request clang TranslationUnit in (* Now retrieve all ctyp values seen so far *) let cache : (ctyp, ctyp) Util.DenseIntMap.t = request clang (CacheFor Cache_ctyp) in Printf.printf "Total unique types in translation unit: %d\n" (Util.DenseIntMap.cardinal cache); (* Iterate and count pointer types *) let ptr_count = Util.DenseIntMap.fold (fun _key ty acc -> match ty.t with | PointerType _ -> acc + 1 | _ -> acc ) cache 0 in Printf.printf "Pointer types: %d\n" ptr_count ) ``` -------------------------------- ### Clang.Diagnostic.show Source: https://context7.com/antique-team/clangml/llms.txt Emits a structured diagnostic with ANSI color. It resolves the location of a diagnostic and prints a GCC-style diagnostic line with ANSI color codes. The level can be Warning or Error. ```APIDOC ## `Clang.Diagnostic.show` — Emit a structured diagnostic with ANSI colour Resolves the `Sloc.t` in a `Diagnostic.diagnostic` record to a presumed location and prints a GCC-style diagnostic line (filename:line:col: level: message [flag, standard]) using `ANSITerminal` colour codes. The level can be `Warning` or `Error`. ```ocaml open Clang.Api open Clang.Diagnostic open Clang.Sloc let emit_warning clang (sloc : Clang.Ast.sloc) message = let diag = { diag_loc = sloc.Clang.Ast.loc_s; diag_msg = message; diag_std = Std_C "6.5.3.2"; diag_flg = Wreserved_name; diag_lvl = Warning; } in show clang diag let () = parse ["target.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | Clang.Ast.TranslationUnitDecl (d :: _) -> emit_warning clang d.Clang.Ast.d_sloc "example diagnostic from OCaml analysis" | _ -> () ) (* Output to stderr (with ANSI bold/colour): target.c:1:1: warning: example diagnostic from OCaml analysis [-Wreserved-name, ISO C99 §6.5.3.2] *) ``` ``` -------------------------------- ### Check C reserved-name violations with Clang.Analysis.NamingConvention.analyse_decl Source: https://context7.com/antique-team/clangml/llms.txt Walks declarations in a translation unit and emits diagnostics for names reserved by the C standard. Requires C99 standard compliance. ```ocaml open Clang.Api open Clang.Analysis let () = parse ["-std=c99"; "user_code.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | Clang.Ast.TranslationUnitDecl decls -> (* Filter to user-defined declarations before checking *) let user_decls = List.filter (fun d -> Clang.Sloc.is_valid d.Clang.Ast.d_sloc.Clang.Ast.loc_s && request clang (FileCharacteristic d.Clang.Ast.d_sloc.Clang.Ast.loc_s) = Clang.Sloc.C_User ) decls in List.iter (fun d -> NamingConvention.analyse_decl clang d) user_decls | _ -> () ) (* For a file containing: int __bad_name = 1; int _Bad_name = 2; int good_name = 3; Prints to stderr (with ANSI colour): user_code.c:1:5: warning: reserved variable name `__bad_name' [-Wreserved-name, ISO C99 §7.1.3] user_code.c:2:5: warning: reserved variable name `_Bad_name' [-Wreserved-name, ISO C99 §7.1.3] *) ``` -------------------------------- ### Determine if Code is User-Defined with FileCharacteristic Source: https://context7.com/antique-team/clangml/llms.txt Determines if a source location corresponds to user code, system header, or external system header. Use this to filter out declarations originating from system headers. Checks if `sloc.Clang.Ast.loc_s` is valid. ```ocaml open Clang.Api open Clang.Sloc let is_user_code clang (sloc : Clang.Ast.sloc) = if Sloc.is_valid sloc.Clang.Ast.loc_s then request clang (FileCharacteristic sloc.Clang.Ast.loc_s) = C_User else false let () = parse ["-std=c99"; "input.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | Clang.Ast.TranslationUnitDecl decls -> let user_decls = List.filter (fun d -> is_user_code clang d.Clang.Ast.d_sloc) decls in Printf.printf "%d user-defined declarations\n" (List.length user_decls) | _ -> () ) ``` -------------------------------- ### Clang.Api.request Source: https://context7.com/antique-team/clangml/llms.txt Issues a typed query to the Clang plugin via a GADT request. The request type determines the return type at compile time, ensuring type safety. It raises `Clang.Api.E` on plugin-side errors. ```APIDOC ## `Clang.Api.request` — Issue a typed query to the Clang plugin Sends a GADT `request` value over the pipe to the plugin and returns the typed response. The request type determines the return type at compile time, preventing mismatched response handling. Raises `Clang.Api.E` on plugin-side errors. ```ocaml open Clang.Api open Clang.Ast let () = parse ["example.c"] (fun clang -> (* Compose two requests into a single round-trip *) let (filename, tu) : string * decl = request clang (Compose (Filename, TranslationUnit)) in Printf.printf "Parsing: %s\n" filename; (* Query size/alignment of a type via a ctyp Ref.t *) (* (assuming we already have a ctyp ref `ty_ref` from traversal) *) (match tu.d with | TranslationUnitDecl (first :: _) -> (match first.d with | VarDecl (tloc, name, _) -> let ty_ref = tloc.tl_type.t_cref in let sz : int64 = request clang (SizeofType ty_ref) in let aln : int = request clang (AlignofType ty_ref) in Printf.printf "Variable '%s': sizeof=%Ld alignof=%d\n" name sz aln | _ -> ()) | _ -> ()); (* Ask whether the first declaration's location is in the main file *) (match tu.d with | TranslationUnitDecl (d :: _) -> let in_main : bool = request clang (IsFromMainFile d.d_sloc.loc_s) in Printf.printf "First decl is from main file: %b\n" in_main | _ -> ()) ) ``` ``` -------------------------------- ### Clang.Api.request with PresumedLoc Source: https://context7.com/antique-team/clangml/llms.txt Converts an opaque `Sloc.t` source-location token into a human-readable `presumed_loc` record containing filename, line number, and column. The "presumed" location accounts for `#line` directives. ```APIDOC ## `Clang.Api.request` with `PresumedLoc` — Resolve a source location to file/line/column Converts an opaque `Sloc.t` source-location token into a human-readable `presumed_loc` record containing filename, line number, and column. The "presumed" location accounts for `#line` directives. ```ocaml open Clang.Api open Clang.Ast open Clang.Sloc let print_location clang (sloc : Ast.sloc) = if is_valid sloc.loc_s then begin let ploc : presumed_loc = request clang (PresumedLoc sloc.loc_s) in if is_valid_presumed ploc then Printf.printf "%s:%d:%d\n" ploc.loc_filename ploc.loc_line ploc.loc_column else Printf.printf "\n" end let () = parse ["foo.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | TranslationUnitDecl decls -> List.iter (fun d -> print_string "decl at: "; print_location clang d.d_sloc ) decls | _ -> () ) (* Output example: decl at: foo.c:1:1 decl at: foo.c:3:1 decl at: foo.c:7:1 *) ``` ``` -------------------------------- ### Clang.Api.request with CacheFor Source: https://context7.com/antique-team/clangml/llms.txt Retrieves the complete type cache as a `DenseIntMap`, mapping `ctyp` values to themselves, indexed by `t_self`. This allows efficient iteration over all types encountered in the translation unit without re-traversing the AST. ```APIDOC ## `Clang.Api.request` with `CacheFor` — Retrieve the complete type cache Returns a `DenseIntMap` containing every `ctyp` value that has been created during the session, indexed by `t_self`. Allows efficient iteration over all types encountered in the translation unit without re-traversing the AST. ```ocaml open Clang.Api open Clang.Ast let () = parse ["big_file.c"] (fun clang -> (* First fetch the TU so the cache is populated *) let _ = request clang TranslationUnit in (* Now retrieve all ctyp values seen so far *) let cache : (ctyp, ctyp) Util.DenseIntMap.t = request clang (CacheFor Cache_ctyp) in Printf.printf "Total unique types in translation unit: %d\n" (Util.DenseIntMap.cardinal cache); (* Iterate and count pointer types *) let ptr_count = Util.DenseIntMap.fold (fun _key ty acc -> match ty.t with | PointerType _ -> acc + 1 | _ -> acc ) cache 0 in Printf.printf "Pointer types: %d\n" ptr_count ) ``` ``` -------------------------------- ### Remove Clang 3.8 Source: https://github.com/antique-team/clangml/blob/master/doc/clang38_to_clang39.txt Remove the existing Clang 3.8 version and its associated development libraries from the system. ```bash sudo apt-get remove clang-3.8 libclang-3.8-dev llvm-3.8-dev ``` -------------------------------- ### Resolve Source Location with PresumedLoc Source: https://context7.com/antique-team/clangml/llms.txt Converts an opaque `Sloc.t` source-location token into a human-readable `presumed_loc` record. The "presumed" location accounts for `#line` directives. Ensure `sloc.loc_s` is valid before calling. ```ocaml open Clang.Api open Clang.Ast open Clang.Sloc let print_location clang (sloc : Ast.sloc) = if is_valid sloc.loc_s then begin let ploc : presumed_loc = request clang (PresumedLoc sloc.loc_s) in if is_valid_presumed ploc then Printf.printf "%s:%d:%d\n" ploc.loc_filename ploc.loc_line ploc.loc_column else Printf.printf "\n" end let () = parse ["foo.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | TranslationUnitDecl decls -> List.iter (fun d -> print_string "decl at: "; print_location clang d.d_sloc ) decls | _ -> () ) ``` -------------------------------- ### Clang.Api.request with DeclOfType Source: https://context7.com/antique-team/clangml/llms.txt Resolves a type reference (`ctyp Ref.t`) back to its declaration (`decl` node). This is useful for navigating from a type's usage to its definition, particularly for typedefs and record/enum types. ```APIDOC ## `Clang.Api.request` with `DeclOfType` — Resolve a type reference back to its declaration Given a `ctyp Ref.t`, returns the `decl` node that declares the underlying type (for typedefs and record/enum types). Useful for navigating from a type use-site to its definition. ```ocaml open Clang.Api open Clang.Ast let () = parse ["structs.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | TranslationUnitDecl decls -> List.iter (fun d -> match d.d with | VarDecl (tloc, var_name, _) -> (match tloc.tl_type.t with | RecordType (_, rec_name) -> (* resolve the record type back to its RecordDecl *) let type_ref = tloc.tl_type.t_cref in let type_decl : decl = request clang (DeclOfType type_ref) in (match type_decl.d with | RecordDecl (_, name, Some members, _) -> Printf.printf "var '%s' has struct '%s' with %d fields\n" var_name name (List.length members) | _ -> ()) | _ -> ()) | _ -> () ) decls | _ -> () ) ``` ``` -------------------------------- ### Resolve Type Reference to Declaration with DeclOfType Source: https://context7.com/antique-team/clangml/llms.txt Given a `ctyp Ref.t`, this resolves the type reference back to its declaration node. It is useful for navigating from a type's usage site to its definition, particularly for typedefs and record/enum types. ```ocaml open Clang.Api open Clang.Ast let () = parse ["structs.c"] (fun clang -> let tu = request clang TranslationUnit in match tu.d with | TranslationUnitDecl decls -> List.iter (fun d -> match d.d with | VarDecl (tloc, var_name, _) -> (match tloc.tl_type.t with | RecordType (_, rec_name) -> (* resolve the record type back to its RecordDecl *) let type_ref = tloc.tl_type.t_cref in let type_decl : decl = request clang (DeclOfType type_ref) in (match type_decl.d with | RecordDecl (_, name, Some members, _) -> Printf.printf "var '%s' has struct '%s' with %d fields\n" var_name name (List.length members) | _ -> ()) | _ -> ()) | _ -> () ) decls | _ -> () ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.