Module Clang__ast

Aliases

type elaborated_type_keyword = Clang__bindings.clang_ext_elaboratedtypekeyword

Keyword associated to an elaborated type: struct, union, enum, ...

type character_kind = Clang__bindings.clang_ext_characterkind

Character kind: ASCII, UTF8, UTF16, ...

type unary_expr_kind = Clang__bindings.clang_ext_unaryexpr

Kind of unary expression: sizeof, alignof, ...

type unary_operator_kind = Clang__bindings.clang_ext_unaryoperatorkind

Kind of unary operator: _++, ++_, -_, &_, ...

type binary_operator_kind = Clang__bindings.clang_ext_binaryoperatorkind

Kind of binary operator: _+_, _=_, _+=_, _<<_, ...

type builtin_type = Clang__bindings.cxtypekind
val equal_elaborated_type_keyword : elaborated_type_keyword -> elaborated_type_keyword -> Ppx_deriving_runtime.bool
val equal_character_kind : character_kind -> character_kind -> Ppx_deriving_runtime.bool
val equal_unary_expr_kind : unary_expr_kind -> unary_expr_kind -> Ppx_deriving_runtime.bool
val equal_unary_operator_kind : unary_operator_kind -> unary_operator_kind -> Ppx_deriving_runtime.bool
val equal_binary_operator_kind : binary_operator_kind -> binary_operator_kind -> Ppx_deriving_runtime.bool
val equal_builtin_type : builtin_type -> builtin_type -> Ppx_deriving_runtime.bool
val compare_elaborated_type_keyword : elaborated_type_keyword -> elaborated_type_keyword -> Ppx_deriving_runtime.int
val compare_character_kind : character_kind -> character_kind -> Ppx_deriving_runtime.int
val compare_unary_expr_kind : unary_expr_kind -> unary_expr_kind -> Ppx_deriving_runtime.int
val compare_unary_operator_kind : unary_operator_kind -> unary_operator_kind -> Ppx_deriving_runtime.int
val compare_binary_operator_kind : binary_operator_kind -> binary_operator_kind -> Ppx_deriving_runtime.int
val compare_builtin_type : builtin_type -> builtin_type -> Ppx_deriving_runtime.int
val pp_elaborated_type_keyword : Format.formatter -> elaborated_type_keyword -> Ppx_deriving_runtime.unit
val show_elaborated_type_keyword : elaborated_type_keyword -> Ppx_deriving_runtime.string
val pp_character_kind : Format.formatter -> character_kind -> Ppx_deriving_runtime.unit
val show_character_kind : character_kind -> Ppx_deriving_runtime.string
val pp_unary_expr_kind : Format.formatter -> unary_expr_kind -> Ppx_deriving_runtime.unit
val show_unary_expr_kind : unary_expr_kind -> Ppx_deriving_runtime.string
val pp_unary_operator_kind : Format.formatter -> unary_operator_kind -> Ppx_deriving_runtime.unit
val show_unary_operator_kind : unary_operator_kind -> Ppx_deriving_runtime.string
val pp_binary_operator_kind : Format.formatter -> binary_operator_kind -> Ppx_deriving_runtime.unit
val show_binary_operator_kind : binary_operator_kind -> Ppx_deriving_runtime.string
val pp_builtin_type : Format.formatter -> builtin_type -> Ppx_deriving_runtime.unit
val show_builtin_type : builtin_type -> Ppx_deriving_runtime.string

Abstractions from libclang's types

type concrete_location = {
filename : string;
line : int;
column : int;
}

A source_location can either be an internal cxsourcelocation from libclang or a concrete_location. concrete_location can be obtained from source_location with Clang.Ast.get_presumed_location or Clang.Ast.get_expansion_location: these functions are identical for source_location constructed from concrete_location, and call Clang.get_presumed_location and Clang.get_expansion_location for libclang's locations.

type source_location =
| Clang of Clang__bindings.cxsourcelocation
| Concrete of concrete_location
type integer_literal =
| Int of int
| CXInt of Clang__bindings.cxint
val equal_integer_literal : integer_literal -> integer_literal -> Ppx_deriving_runtime.bool
val compare_integer_literal : integer_literal -> integer_literal -> Ppx_deriving_runtime.int
type floating_literal =
| Float of float
| CXFloat of Clang__bindings.cxfloat
val equal_floating_literal : floating_literal -> floating_literal -> Ppx_deriving_runtime.bool
val compare_floating_literal : floating_literal -> floating_literal -> Ppx_deriving_runtime.int

Nodes and decorations

type 'qual_type open_decoration =
| Cursor of Clang__bindings.cxcursor
| Custom of {
location : source_location option;
qual_type : 'qual_type option;
}
type ('a, 'qual_type) open_node = {
decoration : 'qual_type open_decoration;
desc : 'a;
}
val equal_open_node : a qual_type. ('a -> 'a -> Ppx_deriving_runtime.bool) -> ('qual_type -> 'qual_type -> Ppx_deriving_runtime.bool) -> ('a'qual_type) open_node -> ('a'qual_type) open_node -> Ppx_deriving_runtime.bool
val compare_open_node : a qual_type. ('a -> 'a -> Ppx_deriving_runtime.int) -> ('qual_type -> 'qual_type -> Ppx_deriving_runtime.int) -> ('a'qual_type) open_node -> ('a'qual_type) open_node -> Ppx_deriving_runtime.int
val pp_open_node : a qual_type. (Format.formatter -> 'a -> Ppx_deriving_runtime.unit) -> (Format.formatter -> 'qual_type -> Ppx_deriving_runtime.unit) -> Format.formatter -> ('a'qual_type) open_node -> Ppx_deriving_runtime.unit
val show_open_node : a qual_type. (Format.formatter -> 'a -> Ppx_deriving_runtime.unit) -> (Format.formatter -> 'qual_type -> Ppx_deriving_runtime.unit) -> ('a'qual_type) open_node -> Ppx_deriving_runtime.string

Visitors for nodes

The following classes define base classes for deriving visitors for AST nodes.

class 'selfbase_iter : object ... end
class 'selfbase_map : object ... end
class virtual +'bbase_reduce : object ... end
class virtual +'cbase_mapreduce : object ... end

Types and nodes

Qualified types

type qual_type = {
cxtype : Clang__bindings.cxtype;
const : bool;

true if the type is const-qualified.

let example = "const int one = 1;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@
  fun ast -> match ast with
  | [{ desc = Var { name = "one";
      qual_type = {
        const = true;
        desc = BuiltinType Int};
      init = Some { desc = IntegerLiteral (Int 1)}}}] -> ()
  | _ -> assert false

let example = "int x;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@
  fun ast -> match ast with
  | [{ desc = Var { name = "x";
      qual_type = {
        const = false;
        desc = BuiltinType Int};
      init = None }}] -> ()
  | _ -> assert false
volatile : bool;

true if the type is volatile-qualified.

let example = "volatile int x;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@
  fun ast -> match ast with
  | [{ desc = Var { name = "x";
      qual_type = {
        volatile = true;
        desc = BuiltinType Int}}}] -> ()
  | _ -> assert false

let example = "int x;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "x";
      qual_type = {
        volatile = false;
        desc = BuiltinType Int}}}] -> ()
  | _ -> assert false
restrict : bool;

true if the type is restrict-qualified.

let example = "int * restrict x;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "x"; qual_type = {
      restrict = true;
      desc = Pointer { desc = BuiltinType Int }}}}] -> ()
  | _ -> assert false

let example = "int * x;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "x"; qual_type = {
      restrict = false;
      desc = Pointer { desc = BuiltinType Int }}}}] -> ()
  | _ -> assert false
desc : type_desc;
}
type type_desc =
| Pointer of qual_type

Pointer.

let example = "char *s;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "s"; qual_type = { desc =
      Pointer { desc = BuiltinType Char_S }}}}] -> ()
  | _ -> assert false
| ConstantArray of {
element : qual_type;
size : int;
}

Constant-sized array.

let example = "char s[42];"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "s"; qual_type = { desc = ConstantArray {
      element = { desc = BuiltinType Char_S };
      size = 42 }}}}] -> ()
  | _ -> assert false
| IncompleteArray of qual_type

Incomplete array.

let example = "struct s { int i; char array[]; };"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl { keyword = Struct; name = "s"; fields = [
      { desc = Field { name = "i"; qual_type = { desc = BuiltinType Int}}};
      { desc = Field { name = "array"; qual_type = { desc =
        IncompleteArray { desc = BuiltinType Char_S }}}}] }}] -> ()
  | _ -> assert false
| VariableArray of {
element : qual_type;
size : expr;
}

Variable array.

let example = "void f(int i, char array[i]);"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Function { name = "f"; function_type =
      { result = { desc = BuiltinType Void };
        args = Some {
          non_variadic = [
            ("i", { desc = BuiltinType Int });
            ("array", { desc = VariableArray {
               element = { desc = BuiltinType Char_S };
               size = { desc = DeclRef "i" }}})];
          variadic = false }}}}] -> ()
  | _ -> assert false
| Elaborated of {
keyword : elaborated_type_keyword;
named_type : qual_type;
}

Elaborated type.

let example = "enum example { A, B, C }; enum example e;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = EnumDecl _ };
     { desc = Var { name = "e"; qual_type = { desc = Elaborated {
      keyword = Enum;
      named_type = { desc = Enum "example" }}}}}] -> ()
  | _ -> assert false
| Enum of string

Enum type.

let example = "enum { A, B, C } e;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = EnumDecl _ };
     { desc = Var { name = "e"; qual_type = { desc = Elaborated {
      keyword = Enum;
      named_type = { desc = Enum "" } as named_type }}}}] ->
        let values =
          match Clang.Type.get_declaration named_type with
          | { desc = EnumDecl { constants }} ->
              constants |> List.map @@ fun (constant : Clang.Ast.enum_constant) ->
                constant.desc.name,
                Clang.Enum_constant.get_value constant
          | _ -> assert false in
        assert (values = ["A", 0; "B", 1; "C", 2]);
  | _ -> assert false
| FunctionType of function_type

Function type.

let example = "int (*p)(void);"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "p"; qual_type = { desc =
      Pointer { desc = FunctionType {
        result = { desc = BuiltinType Int };
        args = Some { non_variadic = []; variadic = false}}}}}}] -> ()
  | _ -> assert false
| Record of string

Record type (either struct or union).

The argument is the name and is the empty string for anonymous struct or union.

let example = "struct { int i; float f; } s;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl { keyword = Struct }};
     { desc = Var { name = "s"; qual_type = { desc = Elaborated {
      keyword = Struct;
      named_type = { desc = Record "" } as named_type }}}}] ->
        let fields = named_type |> Clang.Type.list_of_fields in
        begin
          match fields with
          | [ { desc = Field {
                  name = "i";
                  qual_type = { desc = BuiltinType Int }}};
              { desc = Field {
                  name = "f";
                  qual_type = { desc = BuiltinType Float }}}] -> ()
          | _ ->
              Format.eprintf "%a@." (Format.pp_print_list
                ~pp_sep:Format.pp_print_newline
                Clang.Ast.pp_decl) fields;
              assert false
        end
  | _ -> assert false

let example = "union { int i; float f; } u;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl { keyword = Union }};
     { desc = Var { name = "u"; qual_type = { desc = Elaborated {
      keyword = Union;
      named_type = { desc = Record "" } as named_type }}}}] ->
        let fields = named_type |> Clang.Type.list_of_fields in
        begin
          match fields with
          | [ { desc = Field {
                  name = "i";
                  qual_type = { desc = BuiltinType Int }}};
              { desc = Field {
                  name = "f";
                  qual_type = { desc = BuiltinType Float }}}] -> ()
          | _ ->
              Format.eprintf "%a@." (Format.pp_print_list
                ~pp_sep:Format.pp_print_newline
                Clang.Ast.pp_decl) fields;
              assert false
        end
  | _ -> assert false
| Typedef of string

Typedef type.

let example = "typedef struct { int i; float f; } struct_t; struct_t s;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl { keyword = Struct }}; { desc = TypedefDecl _ };
     { desc = Var { name = "s";
       qual_type = { desc = Typedef "struct_t" } as qual_type }}] ->
        let fields = qual_type |>
          Clang.Type.get_typedef_underlying_type |>
          Clang.Type.list_of_fields in
        begin
          match fields with
          | [ { desc = Field {
                  name = "i";
                  qual_type = { desc = BuiltinType Int }}};
              { desc = Field {
                  name = "f";
                  qual_type = { desc = BuiltinType Float }}}] -> ()
          | _ ->
              Format.eprintf "%a@." (Format.pp_print_list
                ~pp_sep:Format.pp_print_newline
                Clang.Ast.pp_decl) fields;
              assert false
        end
  | _ -> assert false
| Complex of qual_type

Complex number type (C99).

let example = "double _Complex c;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast ->
  match ast |> List.rev |> List.hd with
  | { desc = Var { name = "c";
      qual_type = { desc = Complex { desc = BuiltinType Double }}}} -> ()
  | _ -> assert false

let example = "float _Complex c;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast ->
  match ast |> List.rev |> List.hd with
  | { desc = Var { name = "c";
      qual_type = { desc = Complex { desc = BuiltinType Float }}}} -> ()
  | _ -> assert false
| ParenType of qual_type

Parenthesized type.

Warning: parenthesized type only occurs with Clang <7.0.0 and when ~ignore_paren_in_types:false argument is passed to the AST converting function. From 7.0.0, Clang automatically passes through parentheses in types.

let example = "int (*p)(void);"

let () =
  check Clang.Ast.pp_decl (parse_declaration_list
    ~options:(Clang.Ast.Options.make ~ignore_paren_in_types:false ())) example @@
  fun ast -> match ast with
  | [{ desc = Var { name = "p"; qual_type = { desc =
      Pointer { desc = FunctionType {
        result = { desc = BuiltinType Int };
        args = Some { non_variadic = []; variadic = false}}}}}}] ->
      assert (Clang.get_clang_version () >= "clang version 7.0.0")
  | [{ desc = Var { name = "p"; qual_type = { desc =
      Pointer { desc = ParenType { desc = FunctionType {
        result = { desc = BuiltinType Int };
        args = Some { non_variadic = []; variadic = false}}}}}}}] ->
      assert (Clang.get_clang_version () < "clang version 7.0.0")
  | _ -> assert false
| BuiltinType of builtin_type

Built-in type.

let example = "_Bool s;"

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast ->
  match ast |> List.rev |> List.hd with
  | { desc = Var { name = "s";
      qual_type = { desc = BuiltinType Bool}}} -> ()
  | _ -> assert false
type function_type = {
calling_conv : Clang__bindings.cxcallingconv;

Calling convention.

let example = "void f(void);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { calling_conv = C }}}] -> ()
    | _ -> assert false

let example = {| __attribute((pcs("aapcs"))) void f(void); |}

let () =
    check Clang.Ast.pp_decl
      (parse_declaration_list ~command_line_args:["-target"; "arm"])
      example @@
    fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { calling_conv = AAPCS }}}] ->
        assert (
          Clang.get_clang_version () < "clang version 3.8.0" ||
          Clang.get_clang_version () >= "clang version 3.9.0")
    | [{ desc = Function {
        name = "f"; 
        function_type = { calling_conv = C }}}] ->
        assert (
          Clang.get_clang_version () >= "clang version 3.8.0" &&
          Clang.get_clang_version () < "clang version 3.9.0")
    | _ -> assert false
result : qual_type;

Result type.

let example = "void f(void);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { result = { desc = BuiltinType Void }}}}] -> ()
    | _ -> assert false

let example = "f(void);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { result = { desc = BuiltinType Int }}}}] -> ()
    | _ -> assert false
args : args option;

Argument types. None for K&R-style 'int foo()' function.

let example = "void f(void);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { args = Some {
          non_variadic = [];
          variadic = false }}}}] -> ()
    | _ -> assert false

let example = "void f();"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { args = None }}}] -> ()
    | _ -> assert false
}

Function type.

type args = {
non_variadic : (string * qual_type) list;

Non-variadic arguments: the list gives for each argument its name and its type.

For a function type which is not attached to an actual function declaration, all arguments have the empty name "", since Clang does not keep argument names in function types.

let example = "void f(int i);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { args = Some {
          non_variadic = ["i", { desc = BuiltinType Int }];
          variadic = false }}}}] -> ()
    | _ -> assert false

let example = "void f(int);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { args = Some {
          non_variadic = ["", { desc = BuiltinType Int }];
          variadic = false }}}}] -> ()
    | _ -> assert false

let example = "typedef void (*f)(int x);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = TypedefDecl {
        name = "f"; 
        underlying_type = { desc =
          Pointer { desc = FunctionType { args = Some {
            non_variadic = ["", { desc = BuiltinType Int }];
            variadic = false }}}}}}] -> ()
    | _ -> assert false
variadic : bool;

True if the function type is variadic.

let example = "void f(int i, ...);"

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
    | [{ desc = Function {
        name = "f"; 
        function_type = { args = Some {
          non_variadic = ["i", { desc = BuiltinType Int }];
          variadic = true }}}}] -> ()
    | _ -> assert false
}

Function arguments.

Statements

The following example declares the function parse_statement_list that returns the AST obtained from the parsing of source string as a statement list (by putting it in the context of a function): this function is used in the following examples to check Clang.Ast.pp_decl the AST of various types.

let parse_statement_list ?(return_type = "int") ?filename ?command_line_args ?options source =
  match
    Printf.sprintf "%s f(void) { %s }" return_type source |>
    parse_declaration_list ?filename ?command_line_args ?options
  with
  | [{ desc = Function { body = Some { desc = Compound items }}}] -> items
  | _ -> assert false
type stmt = (stmt_descqual_type) open_node
type stmt_desc =
| Null

Null statement.

let example = ";"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Null }] -> ()
  | _ -> assert false
| Compound of stmt list

Compound statement.

let example = "{}"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Compound [] }] -> ()
  | _ -> assert false

let example = "{;;}"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Compound [{ desc = Null }; { desc = Null }] }] -> ()
  | _ -> assert false
| For of {
init : stmt option;
condition_variable : var_decl option;

C++

cond : expr option;
inc : stmt option;
body : stmt;
}

For statement.

let example = "for (;;) {}"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = For {
      init = None;
      condition_variable = None;
      cond = None;
      inc = None;
      body = { desc = Compound [] }}}] -> ()
  | _ -> assert false

let example = "int i; for (i = 0; i < 4; i++) { i; }"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = For {
      init = Some { desc = Expr { desc = BinaryOperator {
        lhs = { desc = DeclRef "i"};
        kind = Assign;
        rhs = { desc = IntegerLiteral (Int 0)}}}};
      condition_variable = None;
      cond = Some { desc = BinaryOperator {
        lhs = { desc = DeclRef "i"};
        kind = LT;
        rhs = { desc = IntegerLiteral (Int 4)}}};
      inc = Some { desc = Expr { desc = UnaryOperator {
        kind = PostInc;
        operand = { desc = DeclRef "i"}}}};
      body = { desc = Compound [{ desc =
        Expr { desc = DeclRef "i" }}] }}}] -> ()
  | _ -> assert false

let example = "for (int i = 0; i < 4; i++) { i; }"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = For {
      init = Some { desc = Decl [{ desc = Var {
        name = "i";
        qual_type = { desc = BuiltinType Int};
        init = Some { desc = IntegerLiteral (Int 0)}}}] };
      condition_variable = None;
      cond = Some { desc = BinaryOperator {
        lhs = { desc = DeclRef "i"};
        kind = LT;
        rhs = { desc = IntegerLiteral (Int 4)}}};
      inc = Some { desc = Expr { desc = UnaryOperator {
        kind = PostInc;
        operand = { desc = DeclRef "i"}}}};
      body = { desc = Compound [{ desc =
        Expr { desc = DeclRef "i" }}] }}}] -> ()
  | _ -> assert false

let example = "for (int i = 0; int j = i - 1; i--) { j; }"

let () =
  check Clang.Ast.pp_stmt (parse_statement_list
    ~filename:"<string>.cpp") example @@ fun ast -> match ast with
  | [{ desc = For {
      init = Some { desc = Decl [{ desc = Var {
        name = "i";
        qual_type = { desc = BuiltinType Int};
        init = Some { desc = IntegerLiteral (Int 0)}}}] };
      condition_variable = Some { desc = {
        name = "j";
        qual_type = { desc = BuiltinType Int};
        init = Some { desc = BinaryOperator {
          lhs = { desc = DeclRef "i"};
          kind = Sub;
          rhs = { desc = IntegerLiteral (Int 1)}}}}};
      cond = Some { desc = DeclRef "j" };
      inc = Some { desc = Expr { desc = UnaryOperator {
        kind = PostDec;
        operand = { desc = DeclRef "i"}}}};
      body = { desc = Compound [{ desc =
        Expr { desc = DeclRef "j" }}] }}}] -> ()
  | _ -> assert false
| If of {
init : stmt option;

C++17

condition_variable : var_decl option;

C++

cond : expr;
then_branch : stmt;
else_branch : stmt option;
}

If statement.

let example = "if (1) { 2; } else { 3; }"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = If {
       init = None;
       condition_variable = None;
       cond = { desc = IntegerLiteral (Int 1)};
       then_branch = { desc = Compound [{
         desc = Expr { desc = IntegerLiteral (Int 2)}}] };
       else_branch = Some { desc = Compound [{
         desc = Expr { desc = IntegerLiteral (Int 3)}}] }}}] -> ()
  | _ -> assert false

let example = "if (1) { 2; }"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = If {
       init = None;
       condition_variable = None;
       cond = { desc = IntegerLiteral (Int 1)};
       then_branch = { desc = Compound [{
         desc = Expr { desc = IntegerLiteral (Int 2)}}] };
       else_branch = None }}] -> ()
  | _ -> assert false

let example = "if (int i = 1) { i; }"

let () =
  check Clang.Ast.pp_stmt
    (parse_statement_list ~filename:"<string>.cpp") example @@
  fun ast -> match ast with
  | [{ desc = If {
       init = None;
       condition_variable = Some ({ desc = {
         qual_type = { desc = BuiltinType Int};
         name = "i";
         init = Some { desc = IntegerLiteral (Int 1) }}});
       cond = { desc = DeclRef "i"};
       then_branch = { desc = Compound [{
         desc = Expr { desc = DeclRef "i" }}] };
       else_branch = None }}] -> ()
  | _ -> assert false

Init statements in if (C++17) are available since 3.9.0.

let example = "if (int i = 1; i) { i; }"

let () =
  if Clang.get_clang_version () >= "clang version 3.9.0" then
    check Clang.Ast.pp_stmt (parse_statement_list ~filename:"<string>.cpp") example @@ fun ast -> match ast with
    | [{ desc = If {
         init = Some { desc = Decl [{ desc = Var {
           name = "i";
           qual_type = { desc = BuiltinType Int };
           init = Some { desc = IntegerLiteral (Int 1) }}}] };
         condition_variable = None;
         then_branch = { desc = Compound [{
           desc = Expr { desc = DeclRef "i" }}] };
         else_branch = None }}] -> ()
    | _ -> assert false
| Switch of {
init : stmt option;

C++17

condition_variable : var_decl option;

C++

cond : expr;
body : stmt;
}

Switch statement.

let example = "switch (1) { case 1: f(); break; case 2: break; default:;}"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Switch {
      init = None;
      condition_variable = None;
      cond = { desc = IntegerLiteral (Int 1)};
      body = { desc = Compound [
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 1)};
          body = { desc =
            Expr { desc = Call { callee = { desc = DeclRef "f" }; args = [] }}}}};
        { desc = Break };
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 2)};
          body = { desc = Break }}};
        { desc = Default { desc = Null }}] }}}] -> ()
  | _ -> assert false

let example =
  "switch (int i = 1) { case 1: f(); break; case 2: break; default:;}"

let () =
  check Clang.Ast.pp_stmt (parse_statement_list ~filename:"<string>.cpp") example @@ fun ast -> match ast with
  | [{ desc = Switch {
      init = None;
      condition_variable = Some ({ desc = {
         qual_type = { desc = BuiltinType Int};
         name = "i";
         init = Some { desc = IntegerLiteral (Int 1)}}});
      cond = { desc = DeclRef "i" };
      body = { desc = Compound [
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 1)};
          body = { desc =
            Expr { desc = Call { callee = { desc = DeclRef "f" }; args = [] }}}}};
        { desc = Break };
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 2)};
          body = { desc = Break }}};
        { desc = Default { desc = Null }}] }}}] -> ()
  | _ -> assert false

Init statements in if (C++17) are available since 3.9.0.

let example =
  "switch (int i = 1; i) { case 1: f(); break; case 2: break; default:;}"

let () =
  if Clang.get_clang_version () >= "clang version 3.9.0" then
    check Clang.Ast.pp_stmt
    (parse_statement_list ~filename:"<string>.cpp") example @@
    fun ast -> match ast with
    | [{ desc = Switch {
        init = Some { desc = Decl [{ desc = Var {
           name = "i";
           qual_type = { desc = BuiltinType Int };
           init = Some { desc = IntegerLiteral (Int 1)}}}] };
        condition_variable = None;
        cond = { desc = DeclRef "i" };
        body = { desc = Compound [
          { desc = Case {
            lhs = { desc = IntegerLiteral (Int 1)};
            body = { desc =
              Expr { desc = Call {
                callee = { desc = DeclRef "f" }; args = [] }}}}};
          { desc = Break };
          { desc = Case {
            lhs = { desc = IntegerLiteral (Int 2)};
            body = { desc = Break }}};
          { desc = Default { desc = Null }}] }}}] -> ()
    | _ -> assert false
| Case of {
lhs : expr;
rhs : expr option;

GNU extension: case ranges "case low ... high:"

body : stmt;
}

Case statement.

Note that body only covers the first statement that follows. Other statements are attached to the parent.

let example = "switch (1) { case 1: f(); break; case 2 ... 3: break; default:;}"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example
  @@ fun ast -> match ast with
  | [{ desc = Switch {
      init = None;
      condition_variable = None;
      cond = { desc = IntegerLiteral (Int 1)};
      body = { desc = Compound [
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 1)};
          rhs = None;
          body = { desc =
            Expr { desc = Call {
              callee = { desc = DeclRef "f" }; args = [] }}}}};
        { desc = Break };
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 2)};
          rhs = Some { desc = IntegerLiteral (Int 3)};
          body = { desc = Break }}};
        { desc = Default { desc = Null }}] }}}] -> ()
  | _ -> assert false

let example = "switch (1) { case 1: case 2: case 3: default: ;}"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Switch {
      init = None;
      condition_variable = None;
      cond = { desc = IntegerLiteral (Int 1)};
      body = { desc = Compound [
        { desc = Case {
          lhs = { desc = IntegerLiteral (Int 1)};
          rhs = None;
          body = { desc = Case {
            lhs = { desc = IntegerLiteral (Int 2)};
            rhs = None;
            body = { desc = Case {
              lhs = { desc = IntegerLiteral (Int 3)};
              rhs = None;
              body = { desc = Default { desc = Null }}}}}}}}] }}}] -> ()
  | _ -> assert false
| Default of stmt

Default statement.

Note that the parameter only covers the first statement that follows. Other statements are attached to the parent.

| While of {
condition_variable : var_decl option;

C++

cond : expr;
body : stmt;
}

While statement.

let example = "while (1);"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = While {
      condition_variable = None;
      cond = { desc = IntegerLiteral (Int 1)};
      body = { desc = Null }}}] -> ()
  | _ -> assert false

let example = "while (int i = 1) { i; }"

let () =
  check Clang.Ast.pp_stmt
    (parse_statement_list ~filename:"<string>.cpp") example @@
  fun ast -> match ast with
  | [{ desc = While {
      condition_variable = Some ({ desc = {
         qual_type = { desc = BuiltinType Int};
         name = "i";
         init = Some { desc = IntegerLiteral (Int 1)}}});
      cond = { desc = DeclRef "i" };
      body = { desc = Compound [{ desc = Expr { desc = DeclRef "i" }}] }}}] -> ()
  | _ -> assert false
| Do of {
body : stmt;
cond : expr;
}

Do statement.

let example = "do; while (1);"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Do {
      body = { desc = Null };
      cond = { desc = IntegerLiteral (Int 1)}}}] -> ()
  | _ -> assert false

let example = "do { f(); } while (1);"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Do {
      body = { desc = Compound [{ desc =
        Expr { desc = Call { callee = { desc = DeclRef "f" }; args = [] }}}] };
      cond = { desc = IntegerLiteral (Int 1)}}}] -> ()
  | _ -> assert false
| Label of {
label : label_ref;
body : stmt;
}

Label statement.

let example = "label: 1; 2;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Label {
        label = "label";
        body = { desc = Expr { desc = IntegerLiteral (Int 1)}}}};
      { desc = Expr { desc = IntegerLiteral (Int 2)}}] -> ()
  | _ -> assert false
| Goto of label_ref

Goto statement.

let example = "label: 1; goto label;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Label {
        label = "label";
        body = { desc = Expr { desc = IntegerLiteral (Int 1)}}}};
      { desc = Goto "label" }] -> ()
  | _ -> assert false
| IndirectGoto of expr

Indirect goto statement (Labels as Values GNU extension).

let example = "label: 1; void *ptr = &&label; goto *ptr;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Label {
        label = "label";
        body = { desc = Expr { desc = IntegerLiteral (Int 1)}}}};
      { desc = Decl [{ desc = Var {
        name = "ptr";
        qual_type = { desc = Pointer { desc = BuiltinType Void }};
        init = Some { desc = AddrLabel "label" }}}] };
      { desc = IndirectGoto { desc = DeclRef "ptr"}}] -> ()
  | _ -> assert false
| Continue

Continue statement.

let example = "for (;;) continue;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = For { body = { desc = Continue } }}] -> ()
  | _ -> assert false
| Break

Break statement.

let example = "for (;;) break;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = For { body = { desc = Break } }}] -> ()
  | _ -> assert false
| GCCAsm of string * (string, qual_type) open_node list

GCC assembler statement.

let example = {|
  int src = 1;
  int dst;   

  asm ("mov %1, %0\n\t"
    "add $1, %0"
    : "=r" (dst) 
    : "r" (src));
|}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Decl _ };
     { desc = GCCAsm (
       "mov %1, %0\n\tadd $1, %0",
       [{ desc = "dst" }; { desc = "src" }])}] -> ()
  | _ -> assert false
| MSAsm of string

MS assembler statement.

| Return of expr option

Return statement.

let example = "return;"

let () =
  check Clang.Ast.pp_stmt (parse_statement_list ~return_type:"void") example @@
  fun ast -> match ast with
  | [{ desc = Return None }] -> ()
  | _ -> assert false

let example = "return 1;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Return (Some { desc = IntegerLiteral (Int 1)})}] -> ()
  | _ -> assert false
| Decl of decl list
| Expr of expr
| OtherStmt

Expressions

type expr = (expr_descqual_type) open_node
type expr_desc =
| IntegerLiteral of integer_literal

Integer literal. By default, integer literals are converted if possible into Int and integers too large to be represented as int are not converted. Integer literals can be preserved as CXInt by turning Clang.convert_integer_literals option false.

let example = "0;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example
  @@ fun ast -> match ast with
  | [{ desc = Expr { desc = IntegerLiteral (Int 0) }}] -> ()
  | _ -> assert false

let () =
  check Clang.Ast.pp_stmt (parse_statement_list
    ~options:(Clang.Ast.Options.make ~convert_integer_literals:false ()))
    example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = IntegerLiteral (CXInt _ as zero) }}] ->
      assert (Clang.Ast.int_of_literal zero = 0)
  | _ -> assert false

let large_int = Int64.add (Int64.of_int max_int) 1L
let example = Printf.sprintf "%Ld;" large_int

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = Expr { desc = IntegerLiteral (CXInt _ as large_int') }}] ->
      assert (Clang.Ast.int64_of_literal large_int' = large_int)
  | _ -> assert false
| FloatingLiteral of floating_literal

Floating literal.

By default, floating literals are converted into Float. Floating literals can be preserved as CXFloat by turning Clang.convert_floating_literals option false.

let example = "0.5;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = Expr { desc = FloatingLiteral (Float 0.5) }}] -> ()
  | _ -> assert false

let () =
  check Clang.Ast.pp_stmt (parse_statement_list
    ~options:(Clang.Ast.Options.make ~convert_floating_literals:true ()))
    example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = FloatingLiteral f }}] ->
    assert (Clang.Ast.float_of_literal f = 0.5)
  | _ -> assert false
| StringLiteral of string

String literal.

let example = "\"Hello!\";"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@
  fun ast -> match ast with
  | [{ desc = Expr { desc = StringLiteral "Hello!" }}] -> ()
  | _ -> assert false
| CharacterLiteral of {
kind : character_kind;
value : int;
}

Character literal.

let example = "'a';"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = CharacterLiteral { kind = Ascii; value = 0x61 } }}] -> ()
  | _ -> assert false

let example = "L'a';"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = CharacterLiteral { kind = Wide; value = 0x61 } }}] -> ()
  | _ -> assert false


let example = "u8'a';"

let () =
  if Clang.get_clang_version () >= "clang version 3.6" then
    check Clang.Ast.pp_stmt (parse_statement_list ~filename:"<string>.cpp"
        ~command_line_args:["-std=c++1z"]) example @@
    fun ast -> match ast with
    | [{ desc = Expr { desc = CharacterLiteral { kind = UTF8; value = 0x61 } }}]
      -> assert (Clang.get_clang_version () >= "clang version 3.8.0")
    | [{ desc = Expr { desc = CharacterLiteral { kind = Ascii; value = 0x61 } }}]
      -> assert (Clang.get_clang_version () < "clang version 3.8.0")
    | _ -> assert false

let example = "u'a';"

let () =
  if Clang.get_clang_version () >= "clang version 3.6" then
    check Clang.Ast.pp_stmt parse_statement_list example
    @@ fun ast -> match ast with
    | [{ desc = Expr { desc = CharacterLiteral { kind = UTF16; value = 0x61 } }}]
      -> assert (Clang.get_clang_version () >= "clang version 3.8.0")
    | [{ desc = Expr { desc = CharacterLiteral { kind = UTF8; value = 0x61 } }}]
      -> assert (Clang.get_clang_version () < "clang version 3.8.0")
    | _ -> assert false
| ImaginaryLiteral of expr

Imaginary literal.

let example = "1i;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc =
      ImaginaryLiteral { desc = IntegerLiteral (Int 1)} }}] -> ()
  | _ -> assert false

let example = "2.5i;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc =
      ImaginaryLiteral { desc = FloatingLiteral (Float 2.5)}}}] -> ()
  | _ -> assert false
| UnaryOperator of {
kind : unary_operator_kind;
operand : expr;
}

Unary operator.

let example = "+1;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = UnaryOperator {
      kind = Plus;
      operand = { desc = IntegerLiteral (Int 1)}}}}] -> ()
  | _ -> assert false

let example = "int x; &x;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = UnaryOperator {
      kind = AddrOf;
      operand = { desc = DeclRef "x" }} }}] -> ()
  | _ -> assert false
| BinaryOperator of {
lhs : expr;
kind : binary_operator_kind;
rhs : expr;
}

Binary operator.

let example = "1 + 2;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = BinaryOperator {
      lhs = { desc = IntegerLiteral (Int 1)};
      kind = Add;
      rhs = { desc = IntegerLiteral (Int 2)}}}}] -> ()
  | _ -> assert false

let example = "int i = 2; i *= 3;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = BinaryOperator {
      lhs = { desc = DeclRef "i"};
      kind = MulAssign;
      rhs = { desc = IntegerLiteral (Int 3)}}}}] -> ()
  | _ -> assert false
| DeclRef of string

Declaration reference.

let example = "int i; i;"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = DeclRef "i" }}] -> ()
  | _ -> assert false
| Call of {
callee : expr;
args : expr list;
}

Function call.

let example = "void g(int); g(1);"

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = Call {
      callee = { desc = DeclRef "g" };
      args = [{ desc = IntegerLiteral (Int 1)}] }}}] -> ()
  | _ -> assert false
| Cast of {
kind : cast_kind;
qual_type : qual_type;
operand : expr;
}

Cast.

let example = {| (void * ) "Hello"; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = Cast {
      kind = CStyle;
      qual_type = { desc = Pointer _ };
      operand = { desc = StringLiteral "Hello" }} }}] -> ()
  | _ -> assert false

Implicit casts are removed in the AST unless ~ignore_implicit_cast:false is passed to the converting function.

let example = {| int i; i; |}

let () =
  check Clang.Ast.pp_stmt (parse_statement_list
    ~options:(Clang.Ast.Options.make ~ignore_implicit_cast:false ()))
    example @@
  fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = Cast {
      kind = Implicit;
      qual_type = { desc = BuiltinType Int };
      operand = { desc = DeclRef "i" }} }}] -> ()
  | _ -> assert false
| Member of {
base : expr;
arrow : bool;
field : (string, qual_type) open_node;
}

Member dot or arrow

let example = {| struct s { int i } s; s.i = 0; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = BinaryOperator {
      lhs = { desc = Member {
        base = { desc = DeclRef "s" };
        arrow = false;
        field = { desc = "i" }}};
      kind = Assign;
      rhs = { desc = IntegerLiteral (Int 0)}}}}] -> ()
  | _ -> assert false

let example = {| struct s { int i } *p; p->i = 0; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = BinaryOperator {
      lhs = { desc = Member {
        base = { desc = DeclRef "p" };
        arrow = true;
        field = { desc = "i" }}};
      kind = Assign;
      rhs = { desc = IntegerLiteral (Int 0)}}}}] -> ()
  | _ -> assert false
| ArraySubscript of {
base : expr;
index : expr;
}

Array subscript

let example = {| int a[1]; a[0] = 1; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Decl _ }; { desc = Expr { desc = BinaryOperator {
      lhs = { desc = ArraySubscript {
        base = { desc = DeclRef "a" };
        index = { desc = IntegerLiteral (Int 0)}}};
      kind = Assign;
      rhs = { desc = IntegerLiteral (Int 1)}}}}] -> ()
  | _ -> assert false
| ConditionalOperator of {
cond : expr;
then_branch : expr option;
else_branch : expr;
}

Conditional operator. None in else_branch captures GNU "missing middle" extension.

let example = {| 1 ? 2 : 3; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = ConditionalOperator {
      cond = { desc = IntegerLiteral (Int 1)};
      then_branch = Some { desc = IntegerLiteral (Int 2)};
      else_branch = { desc = IntegerLiteral (Int 3)}}}}] -> ()
  | _ -> assert false

let example = {| 1 ? : 3; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = ConditionalOperator {
      cond = { desc = IntegerLiteral (Int 1)};
      then_branch = None;
      else_branch = { desc = IntegerLiteral (Int 3)}}}}] -> ()
  | _ -> assert false
| Paren of expr

Parenthesed expression.

Parenthesed expression are removed in the AST unless ~ignore_paren:false is passed to the converting function.

let example = {| (1); |}

let () =
  check Clang.Ast.pp_stmt (parse_statement_list
    ~options:(Clang.Ast.Options.make ~ignore_paren:false ()))
    example @@
  fun ast -> match ast with
  | [{ desc = Expr { desc = Paren { desc = IntegerLiteral (Int 1)}}}] -> ()
  | _ -> assert false

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = IntegerLiteral (Int 1)}}] -> ()
  | _ -> assert false

let example = {| int i; sizeof(i); |}

let () =
  check Clang.Ast.pp_stmt (parse_statement_list
    ~options:(Clang.Ast.Options.make ~ignore_paren:false ()))
    example @@
  fun ast -> match ast with
  | [ { desc = Decl _ };
      { desc = Expr { desc = UnaryExpr {
          kind = SizeOf;
          argument = ArgumentExpr { desc = Paren { desc = DeclRef "i" }}} }}] ->
      ()
  | _ -> assert false
| AddrLabel of string

Label address (Labels as Values GNU extension).

let example = {| label: &&label; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Label {
        label = "label";
        body = { desc = Expr { desc = AddrLabel "label" }}}}] ->
      ()
  | _ -> assert false
| InitList of expr list

Initialization list.

let example = {| int a[2] = { 1, 2 }; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Var { name = "a"; qual_type = {
      desc = ConstantArray {
        element = { desc = BuiltinType Int };
        size = 2 }};
      init = Some { desc = InitList [
        { desc = IntegerLiteral (Int 1)};
        { desc = IntegerLiteral (Int 2)}] }}}] -> ()
  | _ -> assert false
| CompoundLiteral of {
qual_type : qual_type;
init : expr;
}

Compound literal C99 6.5.2.5.

let example = {| (int []) { 1, 2 }; |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [{ desc = Expr { desc = CompoundLiteral {
      qual_type = { desc = ConstantArray {
        element = { desc = BuiltinType Int };
        size = 2 }};
      init = { desc = InitList [
        { desc = IntegerLiteral (Int 1)};
        { desc = IntegerLiteral (Int 2)}] }} }}] -> ()
  | _ -> assert false
| UnaryExpr of {
kind : unary_expr_kind;
argument : unary_expr_or_type_trait;
}

Unary expr: sizeof, alignof (C++11), ...

let example = {| int i; sizeof(i); |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [ { desc = Decl _ };
      { desc = Expr { desc = UnaryExpr {
          kind = SizeOf;
          argument = ArgumentExpr { desc = DeclRef "i" }} }}] -> ()
  | _ -> assert false

let example = {| sizeof(int); |}

let () =
  check Clang.Ast.pp_stmt parse_statement_list example @@ fun ast -> match ast with
  | [ { desc = Expr { desc = UnaryExpr {
          kind = SizeOf;
          argument = ArgumentType { desc = BuiltinType Int }} }}] -> ()
  | _ -> assert false

let example = {| alignof(int); |}

let () =
  check Clang.Ast.pp_stmt
    (parse_statement_list ~filename:"<string>.cpp"
      ~command_line_args:["-std=c++11"])
    example @@
  fun ast -> match ast with
  | [ { desc = Expr { desc = UnaryExpr {
          kind = AlignOf;
          argument = ArgumentType { desc = BuiltinType Int }} }}] -> ()
  | _ -> assert false

From Clang>=6.0.0, alignof is available by default with C++.

let () =
  if Clang.get_clang_version () >= "clang version 6.0.0" then
    check Clang.Ast.pp_stmt (parse_statement_list ~filename:"<string>.cpp")
    example @@ fun ast -> match ast with
    | [ { desc = Expr { desc = UnaryExpr {
            kind = AlignOf;
            argument = ArgumentType { desc = BuiltinType Int }} }}] -> ()
    | _ -> assert false
| UnexposedExpr of {
s : string;
}
| OtherExpr
type cast_kind =
| CStyle
| Implicit
type unary_expr_or_type_trait =
| ArgumentExpr of expr
| ArgumentType of qual_type

Declarations

type decl = (decl_descqual_type) open_node
type decl_desc =
| Function of {
linkage : Clang__bindings.cxlinkagekind;
function_type : function_type;
name : string;
body : stmt option;
}

Function definition or forward declaration. In case of function definition, we should have body = Some { desc = Compound list; _ } for some list. In case of forward declaration, body = None.

let example = {| int f(void) {} |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = Function {
      linkage = External;
      function_type = {
        calling_conv = C;
        result = { desc = BuiltinType Int};
        args = Some { non_variadic = []; variadic = false }};
      name = "f";
      body = Some { desc = Compound [] }}}] -> ()
  | _ -> assert false

let example = {| static int f(int x); |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@
  fun ast -> match ast with
  | [{ desc = Function {
      linkage = Internal;
      function_type = {
        calling_conv = C;
        result = { desc = BuiltinType Int};
        args = Some {
          non_variadic = [("x", { desc = BuiltinType Int})];
          variadic = false }};
      name = "f";
      body = None }}] -> ()
  | _ -> assert false
| Var of var_decl_desc

Variable declaration.

let example = {| int x = 1; |}

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@
    fun ast -> match ast with
  | [{ desc = Var {
      linkage = External;
      qual_type = { const = false; desc = BuiltinType Int };
      name = "x";
      init = Some ({ desc = IntegerLiteral (Int 1)})}}] -> ()
  | _ -> assert false

let example = {| const int x = 1; |}

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@
    fun ast -> match ast with
  | [{ desc = Var {
      linkage = External;
      qual_type = { const = true; desc = BuiltinType Int };
      name = "x";
      init = Some ({ desc = IntegerLiteral (Int 1)})}}] -> ()
  | _ -> assert false

let example = {| static int x = 1; |}

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@
    fun ast -> match ast with
  | [{ desc = Var {
      linkage = Internal;
      qual_type = { const = false; desc = BuiltinType Int };
      name = "x";
      init = Some ({ desc = IntegerLiteral (Int 1)})}}] -> ()
  | _ -> assert false
| EnumDecl of {
name : string;
constants : enum_constant list;
}

Enum declaration.

let example = {| enum e { A, B = 2, C }; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = EnumDecl {
      name = "e";
      constants = [
        { desc = { name = "A"; init = None }} as a;
        { desc = {
          name = "B";
          init = Some { desc = IntegerLiteral (Int 2)}}} as b;
        { desc = { name = "C"; init = None }} as c] }}] ->
        assert (Clang.Enum_constant.get_value a = 0);
        assert (Clang.Enum_constant.get_value b = 2);
        assert (Clang.Enum_constant.get_value c = 3)
  | _ -> assert false
| RecordDecl of {
keyword : elaborated_type_keyword;
name : string;
fields : decl list;
}

Record declaration (struct or union).

let example = {| struct s { int i; float f; }; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Struct;
      name = "s";
      fields = [
        { desc = Field { name = "i";
          qual_type = { desc = BuiltinType Int}}};
        { desc = Field { name = "f";
          qual_type = { desc = BuiltinType Float}}}] }}] -> ()
  | _ -> assert false

let example = {| struct s { int a:1; int b:2; int c; }; |}

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Struct;
      name = "s";
      fields = [
        { desc = Field { name = "a";
          qual_type = { desc = BuiltinType Int};
          bitwidth = Some { desc = IntegerLiteral (Int 1)}}} as a;
        { desc = Field { name = "b";
          qual_type = { desc = BuiltinType Int};
          bitwidth = Some { desc = IntegerLiteral (Int 2)}}};
        { desc = Field { name = "c";
          qual_type = { desc = BuiltinType Int};
          bitwidth = None}}] }}] ->
      assert (Clang.Decl.get_field_bit_width a = 1)
  | _ -> assert false

let example = {| union u { int i; float f; }; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Union;
      name = "u";
      fields = [
        { desc = Field { name = "i";
          qual_type = { desc = BuiltinType Int}}};
        { desc = Field { name = "f";
          qual_type = { desc = BuiltinType Float}}}] }}] -> ()
  | _ -> assert false

let example = {| union u { int a:1; int b:2; int c; }; |}

let () =
    check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Union;
      name = "u";
      fields = [
        { desc = Field { name = "a";
          qual_type = { desc = BuiltinType Int};
          bitwidth = Some { desc = IntegerLiteral (Int 1)}}} as a;
        { desc = Field { name = "b";
          qual_type = { desc = BuiltinType Int};
          bitwidth = Some { desc = IntegerLiteral (Int 2)}}};
        { desc = Field { name = "c";
          qual_type = { desc = BuiltinType Int};
          bitwidth = None}}] }}] ->
      assert (Clang.Decl.get_field_bit_width a = 1)
  | _ -> assert false

let example = {| struct s { int label; union { int i; float f; };}; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Struct;
      name = "s";
      fields = [
        { desc = Field { name = "label";
          qual_type = { desc = BuiltinType Int}}};
        { desc = RecordDecl { keyword = Union; name = ""; fields = [
          { desc = Field { name = "i";
            qual_type = { desc = BuiltinType Int}}};
          { desc = Field { name = "f";
            qual_type = { desc = BuiltinType Float}}}] }}] }}] -> ()
  | _ -> assert false

let example = {| union s { int single; struct { int i; float f; };}; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Union;
      name = "s";
      fields = [
        { desc = Field { name = "single";
          qual_type = { desc = BuiltinType Int}}};
        { desc = RecordDecl { keyword = Struct; name = ""; fields = [
          { desc = Field { name = "i";
            qual_type = { desc = BuiltinType Int}}};
          { desc = Field { name = "f";
            qual_type = { desc = BuiltinType Float}}}] }}] }}] -> ()
  | _ -> assert false
| TypedefDecl of {
name : string;
underlying_type : qual_type;
}

Typedef declaration.

Note that if the typedef declares a new underlying type, the declaration of the underlying type precedes the typedef declaration in the AST.

let example = {| typedef int int_t; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = TypedefDecl {
      name = "int_t";
      underlying_type = { desc = BuiltinType Int }}}] -> ()
  | _ -> assert false

let example = {| typedef union u { int i; float f } u_t; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
        keyword = Union;
        name = "u";
        fields = [
          { desc = Field { name = "i";
            qual_type = { desc = BuiltinType Int}}};
          { desc = Field { name = "f";
            qual_type = { desc = BuiltinType Float}}}] }};
      { desc = TypedefDecl {
        name = "u_t";
        underlying_type = { desc = Elaborated {
          keyword = Union;
          named_type = { desc = Record "u" }}}}}] -> ()
  | _ -> assert false

let example = {| typedef union { int i; float f } u_t; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
        keyword = Union;
        name = "";
        fields = [
          { desc = Field {
              name = "i";
              qual_type = { desc = BuiltinType Int}}};
          { desc = Field {
              name = "f";
              qual_type = { desc = BuiltinType Float}}}] }};
      { desc = TypedefDecl {
        name = "u_t";
        underlying_type = { desc = Elaborated {
          keyword = Union;
          named_type = { desc = Record "" }}} as underlying_type }}] ->
        let fields = underlying_type |> Clang.Type.list_of_fields in
        begin
          match fields with
          | [ { desc = Field {
                  name = "i";
                  qual_type = { desc = BuiltinType Int}}};
              { desc = Field {
                  name = "f";
                  qual_type = { desc = BuiltinType Float}}}] -> ()
          | fields ->
              Format.eprintf "%a@." (Format.pp_print_list
                ~pp_sep:Format.pp_print_newline
                Clang.Ast.pp_decl) fields;
              assert false
        end
  | _ -> assert false
| Field of {
name : string;
qual_type : qual_type;
bitwidth : expr option;
}

Record (struct or union) field.

let example = {| struct s { int label; union u { int i; float f; } data;}; |}

let () =
  check Clang.Ast.pp_decl parse_declaration_list example @@ fun ast -> match ast with
  | [{ desc = RecordDecl {
      keyword = Struct;
      name = "s";
      fields = [
        { desc = Field { name = "label";
          qual_type = { desc = BuiltinType Int}}};
        { desc = RecordDecl { keyword = Union; name = "u"; fields = [
          { desc = Field { name = "i";
            qual_type = { desc = BuiltinType Int}}};
          { desc = Field { name = "f";
            qual_type = { desc = BuiltinType Float}}}] }};
        { desc = Field { name = "data";
          qual_type = { desc = Elaborated {
            keyword = Union;
            named_type = { desc = Record "u" }}}}}] }}] -> ()
  | _ -> assert false
| OtherDecl
type label_ref = string
type enum_constant = (enum_constant_descqual_type) open_node
type enum_constant_desc = {
name : string;
init : expr option;
}
type var_decl = (var_decl_descqual_type) open_node
type var_decl_desc = {
linkage : Clang__bindings.cxlinkagekind;
name : string;
qual_type : qual_type;
init : expr option;
}

Translation units

type translation_unit = (translation_unit_descqual_type) open_node
type translation_unit_desc = {
filename : string;
items : decl list;
}
val pp_qual_type : Format.formatter -> qual_type -> Ppx_deriving_runtime.unit
val show_qual_type : qual_type -> Ppx_deriving_runtime.string
val pp_type_desc : Format.formatter -> type_desc -> Ppx_deriving_runtime.unit
val show_type_desc : type_desc -> Ppx_deriving_runtime.string
val pp_function_type : Format.formatter -> function_type -> Ppx_deriving_runtime.unit
val show_function_type : function_type -> Ppx_deriving_runtime.string
val pp_args : Format.formatter -> args -> Ppx_deriving_runtime.unit
val show_args : args -> Ppx_deriving_runtime.string
val pp_stmt : Format.formatter -> stmt -> Ppx_deriving_runtime.unit
val show_stmt : stmt -> Ppx_deriving_runtime.string
val pp_stmt_desc : Format.formatter -> stmt_desc -> Ppx_deriving_runtime.unit
val show_stmt_desc : stmt_desc -> Ppx_deriving_runtime.string
val pp_expr : Format.formatter -> expr -> Ppx_deriving_runtime.unit
val show_expr : expr -> Ppx_deriving_runtime.string
val pp_expr_desc : Format.formatter -> expr_desc -> Ppx_deriving_runtime.unit
val show_expr_desc : expr_desc -> Ppx_deriving_runtime.string
val pp_cast_kind : Format.formatter -> cast_kind -> Ppx_deriving_runtime.unit
val show_cast_kind : cast_kind -> Ppx_deriving_runtime.string
val pp_unary_expr_or_type_trait : Format.formatter -> unary_expr_or_type_trait -> Ppx_deriving_runtime.unit
val show_unary_expr_or_type_trait : unary_expr_or_type_trait -> Ppx_deriving_runtime.string
val pp_decl : Format.formatter -> decl -> Ppx_deriving_runtime.unit
val show_decl : decl -> Ppx_deriving_runtime.string
val pp_decl_desc : Format.formatter -> decl_desc -> Ppx_deriving_runtime.unit
val show_decl_desc : decl_desc -> Ppx_deriving_runtime.string
val pp_label_ref : Format.formatter -> label_ref -> Ppx_deriving_runtime.unit
val show_label_ref : label_ref -> Ppx_deriving_runtime.string
val pp_enum_constant : Format.formatter -> enum_constant -> Ppx_deriving_runtime.unit
val show_enum_constant : enum_constant -> Ppx_deriving_runtime.string
val pp_enum_constant_desc : Format.formatter -> enum_constant_desc -> Ppx_deriving_runtime.unit
val show_enum_constant_desc : enum_constant_desc -> Ppx_deriving_runtime.string
val pp_var_decl : Format.formatter -> var_decl -> Ppx_deriving_runtime.unit
val show_var_decl : var_decl -> Ppx_deriving_runtime.string
val pp_var_decl_desc : Format.formatter -> var_decl_desc -> Ppx_deriving_runtime.unit
val show_var_decl_desc : var_decl_desc -> Ppx_deriving_runtime.string
val pp_translation_unit : Format.formatter -> translation_unit -> Ppx_deriving_runtime.unit
val show_translation_unit : translation_unit -> Ppx_deriving_runtime.string
val pp_translation_unit_desc : Format.formatter -> translation_unit_desc -> Ppx_deriving_runtime.unit
val show_translation_unit_desc : translation_unit_desc -> Ppx_deriving_runtime.string
val equal_qual_type : qual_type -> qual_type -> Ppx_deriving_runtime.bool
val equal_type_desc : type_desc -> type_desc -> Ppx_deriving_runtime.bool
val equal_function_type : function_type -> function_type -> Ppx_deriving_runtime.bool
val equal_args : args -> args -> Ppx_deriving_runtime.bool
val equal_stmt : stmt -> stmt -> Ppx_deriving_runtime.bool
val equal_stmt_desc : stmt_desc -> stmt_desc -> Ppx_deriving_runtime.bool
val equal_expr : expr -> expr -> Ppx_deriving_runtime.bool
val equal_expr_desc : expr_desc -> expr_desc -> Ppx_deriving_runtime.bool
val equal_cast_kind : cast_kind -> cast_kind -> Ppx_deriving_runtime.bool
val equal_unary_expr_or_type_trait : unary_expr_or_type_trait -> unary_expr_or_type_trait -> Ppx_deriving_runtime.bool
val equal_decl : decl -> decl -> Ppx_deriving_runtime.bool
val equal_decl_desc : decl_desc -> decl_desc -> Ppx_deriving_runtime.bool
val equal_label_ref : label_ref -> label_ref -> Ppx_deriving_runtime.bool
val equal_enum_constant : enum_constant -> enum_constant -> Ppx_deriving_runtime.bool
val equal_enum_constant_desc : enum_constant_desc -> enum_constant_desc -> Ppx_deriving_runtime.bool
val equal_var_decl : var_decl -> var_decl -> Ppx_deriving_runtime.bool
val equal_var_decl_desc : var_decl_desc -> var_decl_desc -> Ppx_deriving_runtime.bool
val equal_translation_unit : translation_unit -> translation_unit -> Ppx_deriving_runtime.bool
val equal_translation_unit_desc : translation_unit_desc -> translation_unit_desc -> Ppx_deriving_runtime.bool
val compare_qual_type : qual_type -> qual_type -> Ppx_deriving_runtime.int
val compare_type_desc : type_desc -> type_desc -> Ppx_deriving_runtime.int
val compare_function_type : function_type -> function_type -> Ppx_deriving_runtime.int
val compare_args : args -> args -> Ppx_deriving_runtime.int
val compare_stmt : stmt -> stmt -> Ppx_deriving_runtime.int
val compare_stmt_desc : stmt_desc -> stmt_desc -> Ppx_deriving_runtime.int
val compare_expr : expr -> expr -> Ppx_deriving_runtime.int
val compare_expr_desc : expr_desc -> expr_desc -> Ppx_deriving_runtime.int
val compare_cast_kind : cast_kind -> cast_kind -> Ppx_deriving_runtime.int
val compare_unary_expr_or_type_trait : unary_expr_or_type_trait -> unary_expr_or_type_trait -> Ppx_deriving_runtime.int
val compare_decl : decl -> decl -> Ppx_deriving_runtime.int
val compare_decl_desc : decl_desc -> decl_desc -> Ppx_deriving_runtime.int
val compare_label_ref : label_ref -> label_ref -> Ppx_deriving_runtime.int
val compare_enum_constant : enum_constant -> enum_constant -> Ppx_deriving_runtime.int
val compare_enum_constant_desc : enum_constant_desc -> enum_constant_desc -> Ppx_deriving_runtime.int
val compare_var_decl : var_decl -> var_decl -> Ppx_deriving_runtime.int
val compare_var_decl_desc : var_decl_desc -> var_decl_desc -> Ppx_deriving_runtime.int
val compare_translation_unit : translation_unit -> translation_unit -> Ppx_deriving_runtime.int
val compare_translation_unit_desc : translation_unit_desc -> translation_unit_desc -> Ppx_deriving_runtime.int
include sig ... end
class virtual +'biter : object ... end
include sig ... end
class virtual +'cmap : object ... end
include sig ... end
class virtual +'breduce : object ... end
include sig ... end
class virtual +'cmapreduce : object ... end
type decoration = qual_type open_decoration
type 'a node = ('aqual_type) open_node