Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file C_AST.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2019 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(**
C_AST - Simpler C AST
Provides a simpler version of the AST converted from Clang.
The goal of this AST is to:
- be independent from Clang's version
- support linking of several translation units into a single AST
- only support C for now
*)typeuid=Clang_AST.uid(** Unique identifiers (for variables and functions). *)moduleUidMap=Map.Make(structtypet=uidletcompare=compareend)moduleUidSet=Set.Make(structtypet=uidletcompare=compareend)moduleStringMap=Map.Make(String)typerange=Clang_AST.rangemoduleRangeMap=Mopsa_utils.MapExt.Make(structtypet=rangeletcompare=Stdlib.compareend)(** Source locations. *)typecomment=Clang_AST.comment(** Comments in file. *)typemacro=Clang_AST.macro(** preprocessor macros *)typecharacter_kind=Clang_AST.character_kindtypetarget_info=Clang_AST.target_info(** {2 Operators} *)typebinary_arithmetic=|ADD(** + *)|SUB(** - *)|MUL(** * *)|DIV(** / *)|MOD(** % *)|LEFT_SHIFT(** << *)|RIGHT_SHIFT(** >> *)|BIT_AND(** & *)|BIT_OR(** | *)|BIT_XOR(** ^ *)typebinary_logical=|LESS(** < *)|LESS_EQUAL(** <= *)|GREATER(** > *)|GREATER_EQUAL(** >= *)|EQUAL(** == *)|NOT_EQUAL(** != *)|LOGICAL_AND(** && *)|LOGICAL_OR(** || *)typebinary_operator=|O_arithmeticofbinary_arithmetic|O_logicalofbinary_logicaltypeunary_operator=|NEG(** - *)|BIT_NOT(** ~ *)|LOGICAL_NOT(** ! *)typeexplicitness=|EXPLICIT|IMPLICIT(** Whether a cast is explicit (in the source) or implicit (added for implicit conversions *)typeinc_location=|PRE|POST(** Whether an incrementation is performed before (PRE) or after (POST) the expression value is used *)typeinc_direction=|INC|DEC(** Whether an incrementation is ++ or -- *)(** {2 Types} *)typesignedness=SIGNED|UNSIGNED(** Whether an integer type is signed or not. *)typeinteger_type=|Charofsignedness(** plain 'char', where the signeness is defined by the platform *)|SIGNED_CHAR|UNSIGNED_CHAR|SIGNED_SHORT|UNSIGNED_SHORT|SIGNED_INT|UNSIGNED_INT|SIGNED_LONG|UNSIGNED_LONG|SIGNED_LONG_LONG|UNSIGNED_LONG_LONG|SIGNED_INT128|UNSIGNED_INT128(** Integer types. *)typefloat_type=FLOAT|DOUBLE|LONG_DOUBLE|FLOAT128(** Floating-point types. *)typerecord_kind=STRUCT|UNION(** Whether a record type is a struct or a union. *)typequalifier={qual_is_const:bool;}(** Type qualifiers. For now, only 'const' is useful. *)(** Types. *)typetyp=|T_void(** Void type. *)|T_bool|T_integerofinteger_type|T_floatoffloat_type|T_complexoffloat_type|T_pointeroftype_qual(** Scalar types. *)|T_arrayoftype_qual*array_length(** Arrays. *)|T_bitfieldoftyp(* integer or enum type *)*int(* bit-size *)(** Bitfields, with bit-width, only used in struct. *)|T_functionoffunction_typeoption(** Function, with or without a prototype *)|T_builtin_fn(** Built-in functions *)|T_typedefoftypedef(** Typedefs *)|T_recordofrecord_type(** struct and union *)|T_enumofenum_type(** enums *)|T_vectorofvector_type(** GCC vectors *)|T_unknown_builtinofstring(** unknown builtin *)andtype_qual=typ*qualifier(** Type with qualifier. *)andtypedef={typedef_org_name:string;(** name as in source *)mutabletypedef_uid:uid;mutabletypedef_unique_name:string;(** unique name *)mutabletypedef_def:type_qual;(** declaration *)mutabletypedef_range:range;(** declaration location *)mutabletypedef_com:commentlist;(** comments associated to the declaration *)}andrecord_type={record_kind:record_kind;record_org_name:string;(** name as in source, may be empty *)mutablerecord_uid:uid;(** unique identifier *)mutablerecord_unique_name:string;(** unique, non-empty name *)mutablerecord_defined:bool;(** false if only declared *)mutablerecord_sizeof:Z.t;(** size of record, in bytes *)mutablerecord_alignof:Z.t;(** alignment, in bytes *)mutablerecord_fields:record_fieldarray;mutablerecord_range:range;(** declaration location *)mutablerecord_com:commentlist;(** comments associated to the declaration *)}(** Struct or union type. *)andrecord_field={field_uid:uid;(** unique identifier *)field_org_name:string;(** may be empty for anonymous or padding fields *)field_name:string;(** non-empty name *)field_offset:int;field_bit_offset:int;mutablefield_type:type_qual;field_range:range;(** declaration location *)field_record:record_type;field_index:int;mutablefield_com:commentlist;(** comments associated to the declaration *)}(** Struct or union field. *)andenum_type={enum_org_name:string;(** name as in source, may be empty *)mutableenum_uid:uid;(** unoque identifier *)mutableenum_unique_name:string;(** unique, non-empty name *)mutableenum_defined:bool;(** false if only declared *)mutableenum_values:enum_valuelist;mutableenum_integer_type:integer_typeoption;mutableenum_range:range;(** declaration location *)mutableenum_com:commentlist;(** comments associated to the declaration *)}(** Enumerated type. *)andenum_value={enum_val_uid:uid;(** unique identifier *)enum_val_org_name:string;(** name as in source *)enum_val_unique_name:string;(** unique name *)enum_val_value:Z.t;enum_val_enum:enum_type;enum_val_range:range;mutableenum_val_com:commentlist;(** comments associated to the declaration *)}(** A possible value in an enumerated type. *)andarray_length=|No_length|Length_cstofZ.t|Length_exprofexpr(** Length of an array. *)andfunction_type={mutableftype_return:type_qual;mutableftype_params:type_quallist;ftype_variadic:bool;}(** Type of functions and prototypes. *)andvector_type={vector_type:type_qual;vector_size:int;vector_kind:int;}(** GCC vector types. *)(** {2 Variables and functions} *)andvariable={var_uid:uid;(** unique identifier *)var_org_name:string;(** original name *)var_unique_name:string;(** unique name for globals and statics *)mutablevar_kind:variable_kind;(** variable kind and life-time *)mutablevar_type:type_qual;mutablevar_init:initoption;mutablevar_before_stmts:statementlist;(** statements executed before the declaration of the variable *)mutablevar_after_stmts:statementlist;(** statements executed after the declaration of the variable *)mutablevar_range:range;mutablevar_com:commentlist;(** comments associated to the declaration *)}andvariable_kind=|Variable_global(** global shared among translation units *)|Variable_extern(** declared but not defined *)|Variable_localoffunc(** local to a function *)|Variable_parameteroffunc(** formal argument *)|Variable_file_staticoftranslation_unit(** restricted to a translation unit *)|Variable_func_staticoffunc(** restricted to a function *)andfunc={func_uid:uid;(** unique identifier *)func_org_name:string;(** original name *)func_unique_name:string;(** unique name for globals and statics *)func_is_static:bool;mutablefunc_return:type_qual;(** type of returned value *)mutablefunc_parameters:variablearray;(** function parameters *)mutablefunc_body:blockoption;(** function body *)mutablefunc_static_vars:variablelist;(** static variables declared in the function *)mutablefunc_local_vars:variablelist;(** local variables declared in the function (excluding parameters) *)mutablefunc_variadic:bool;(** whether the has a variable number of arguments *)mutablefunc_range:range;(** range of the full declaration *)mutablefunc_name_range:range;(** range of the name part of the declaration *)mutablefunc_com:(comment*macroStringMap.t)list;(** comments associated to the declaration *)}(** {2 Statements and expressions} *)andstatement=statement_kind*rangeandblock={blk_stmts:statementlist;(** statements in the block *)blk_local_vars:variablelist;(** local variables declared within the block (excluding sub-blocks); these should be deallocated when exiting the block *)}andstatement_kind=|S_local_declarationofvariable(** local variable declaration *)|S_expressionofexpr(** expression statement *)|S_blockofblock(** statement block *)|S_ifofexpr(** condition *)*block(** then branch *)*block(** else branch *)(** if conditional *)|S_whileofexpr(** condition *)*block(** body *)(** while loop *)|S_do_whileofblock(** body *)*expr(** condition *)(** do-while loop *)|S_forofblock(** init *)*exproption(** condition *)*exproption(** increment *)*block(** body *)(** for loop; the scope of the locals declared in the init block is the while for loop *)|S_jumpofjump_kind(** jump instruction *)|S_targetoftarget_kind(** target of a jump *)|S_asmofasm_kind(** asm statement *)andjump_kind=|S_gotoofstring*scope_update|S_breakofscope_update|S_continueofscope_update|S_returnofexproption*scope_update|S_switchofexpr*block(** various ways to jump *)andtarget_kind=|S_labelofstring|S_caseofexprlist*scope_update|S_defaultofscope_update(** various targets of jumps *)andscope_update={mutablescope_var_added:variablelist;mutablescope_var_removed:variablelist;}(** variables to remove and to add (uninitialized) when jumping into
another scope;
may be attached to a jump source (break, continue, return, goto)
or a jump target (switch case and default), depending on
what's more convinient
*)andasm_kind={asm_style:asm_style;asm_is_simple:bool;asm_is_volatile:bool;asm_body:string;asm_outputs:asm_outputarray;asm_inputs:asm_inputarray;asm_clobbers:stringarray;asm_labels:stringarray;}(** and asm statement *)andasm_output={asm_output_string:string;asm_output_expr:expr;asm_output_constraint:asm_output_constraint;}andasm_input={asm_input_string:string;asm_input_expr:expr;}andasm_style=Clang_AST.asm_styleandasm_output_constraint=Clang_AST.asm_output_constraintandexpr=expr_kind*type_qual*rangeandexpr_kind=|E_conditionalofexpr(** condition *)*expr(** then *)*expr(** else *)(** ?: ternary operator *)|E_binary_conditionalofexpr(** condition and then *)*expr(** else *)(** binary version of the ?: operator *)|E_array_subscriptofexpr(** array *)*expr(** index *)(** Array access. *)|E_member_accessofexpr(** record *)*int(** field index *)*string(** field *)(** record.field access *)|E_arrow_accessofexpr(** pointer *)*int(** field index *)*string(** field *)(** pointer->field access *)|E_compound_assignofexpr(** lvalue *)*type_qual(** promoted type of lvalue before operation *)*binary_arithmetic(** operator *)*expr(** rvalue *)*type_qual(** type of the result, before converting back to lvalue type *)(** Assignment wth an operation: e1 += e2, etc. *)|E_binaryofbinary_operator*expr(** left argument *)*expr(** right argument *)(** Plain operation. *)|E_assignofexpr(** lvalue *)*expr(** rvalue *)(** Plain assignment *)|E_commaofexpr*expr(** , operator *)|E_unaryofunary_operator*expr|E_incrementofinc_direction*inc_location*expr|E_address_ofofexpr(** & operator (address of lvalue) *)|E_derefofexpr(** * operator (pointer dereference) *)|E_castofexpr*explicitness|E_callofexpr(** target function *)*exprarray(** actual arguments *)|E_character_literalofZ.t*character_kind(** literal character *)|E_integer_literalofZ.t(** literal integer *)|E_float_literalofstring(** literal float, in binary string notation *)|E_string_literalofstring*character_kind|E_compound_literalofinit|E_variableofvariable|E_functionoffunc|E_predefinedofstring(** predefined identifier *)|E_statementofblock(** a block of statements viewed as an expression (GCC extension) *)|E_var_argsofexpr(** __builtin_va_arg *)|E_atomicofint(** operation *)*expr*expr(** vector instructions *)|E_convert_vectorofexpr|E_vector_elementofexpr(** base *)*string(** accessor *)|E_shuffle_vectorofexprarrayandinit=|I_init_exprofexpr|I_init_listofinitlist(** specified elements *)*initoption(** filler *)|I_init_implicitoftype_qualandtranslation_unit={tu_uid:int;tu_name:string;tu_range:range;}andproject={proj_name:string;(** project name *)proj_tu:translation_unitlist;(** translation units composing the project *)proj_target:target_info;proj_typedefs:typedefStringMap.t;(** typedefs, by unique name *)proj_enums:enum_typeStringMap.t;(** enums, by unique name *)proj_records:record_typeStringMap.t;(** records, by unique name *)proj_vars:variableStringMap.t;(** variables with global lifetime, by unique name *)proj_funcs:funcStringMap.t;(** functions, by unique name *)proj_file_scope_asm:stringRangeMap.t;(** file-scope assembly directives *)proj_files:stringlist;(** list of parsed files *)proj_comments:(comment*macroStringMap.t)listRangeMap.t;(** all comments *)proj_macros:macroStringMap.t;(** macros, by name *)}(** A project is a set of translation units linked together. *)(** {2 Useful definitions} *)letno_qual={qual_is_const=false;}(** No qualifier. *)letint_type=T_integerSIGNED_INT,no_qualletbool_type=T_bool,no_qualletvoid_ptr_type=T_pointer(T_void,no_qual),no_qualletuchar_ptr_type=T_pointer(T_integerUNSIGNED_CHAR,no_qual),no_qualletmerge_qualifiers(q1:qualifier)(q2:qualifier):qualifier={qual_is_const=q1.qual_is_const||q2.qual_is_const;}letrecresolve_typedef((t,q):type_qual):type_qual=matchtwith|T_typedeft->lettt,qq=resolve_typedeft.typedef_defintt,merge_qualifiersqqq|_->t,q(** Replace toplevel occurences of typedefs with their definition. *)letrecas_int_type(tq:type_qual):integer_type=matchfst(resolve_typedeftq)with|T_integeri->i|T_enume->(matche.enum_integer_typewith|None->failwith"None"|Somes->s)|T_bool->SIGNED_INT|_->invalid_arg"as_int_type: not an integer type"(** Interprets the type as an integer type, if possible *)letrecas_float_type(tq:type_qual):float_type=matchfst(resolve_typedeftq)with|T_floatf->f|_->invalid_arg"as_float_type: not a float type"(** Interprets the type as an integer type, if possible *)letrectype_is_scalar(t:typ)=matchtwith|T_void->false|T_bool|T_integer_|T_float_|T_pointer_->true|T_array_->false|T_bitfield_->true|T_function_->false|T_builtin_fn->false|T_typedeft->type_is_scalar(fstt.typedef_def)|T_enum_->true|T_record_->false|T_complex_->false|T_vector_->false|T_unknown_builtin_->false(** Whether a type yields a scalar value. *)(** {2 Variable utilities} *)letvariable_is_globalkind=matchkindwith|Variable_extern|Variable_global|Variable_file_static_|Variable_func_static_->true|Variable_local_|Variable_parameter_->false(** Whether variables of this kind have global lifetime or not. *)letvariable_is_statickind=matchkindwith|Variable_file_static_|Variable_func_static_->true|Variable_extern|Variable_global|Variable_local_|Variable_parameter_->false(** Whether variables of this kind are static or not. *)letvariable_is_file_statickind=matchkindwith|Variable_file_static_->true|_->false(** Whether variables of this kind are file-level static. *)