(* * Copyright (c) 2009 - 2013 Monoidics ltd. * Copyright (c) 2013 - present Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) (** The Smallfoot Intermediate Language: Types *) open! IStd module F = Format (** Kinds of integers *) type ikind = | IChar (** [char] *) | ISChar (** [signed char] *) | IUChar (** [unsigned char] *) | IBool (** [bool] *) | IInt (** [int] *) | IUInt (** [unsigned int] *) | IShort (** [short] *) | IUShort (** [unsigned short] *) | ILong (** [long] *) | IULong (** [unsigned long] *) | ILongLong (** [long long] (or [_int64] on Microsoft Visual C) *) | IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft Visual C) *) | I128 (** [__int128_t] *) | IU128 (** [__uint128_t] *) [@@deriving compare] val ikind_is_char : ikind -> bool (** Check whether the integer kind is a char *) val ikind_is_unsigned : ikind -> bool (** Check whether the integer kind is unsigned *) val int_of_int64_kind : int64 -> ikind -> IntLit.t (** Convert an int64 into an IntLit.t given the kind: the int64 is interpreted as unsigned according to the kind *) (** Kinds of floating-point numbers *) type fkind = | FFloat (** [float] *) | FDouble (** [double] *) | FLongDouble (** [long double] *) [@@deriving compare] (** kind of pointer *) type ptr_kind = | Pk_pointer (** C/C++, Java, Objc standard/__strong pointer *) | Pk_reference (** C++ reference *) | Pk_objc_weak (** Obj-C __weak pointer *) | Pk_objc_unsafe_unretained (** Obj-C __unsafe_unretained pointer *) | Pk_objc_autoreleasing (** Obj-C __autoreleasing pointer *) [@@deriving compare] val equal_ptr_kind : ptr_kind -> ptr_kind -> bool type type_quals [@@deriving compare] val mk_type_quals : ?default:type_quals -> ?is_const:bool -> ?is_restrict:bool -> ?is_volatile:bool -> unit -> type_quals val is_const : type_quals -> bool val is_restrict : type_quals -> bool val is_volatile : type_quals -> bool (** types for sil (structured) expressions *) type t = {desc: desc; quals: type_quals} [@@deriving compare] and desc = | Tint of ikind (** integer type *) | Tfloat of fkind (** float type *) | Tvoid (** void type *) | Tfun of bool (** function type with noreturn attribute *) | Tptr of t * ptr_kind (** pointer type *) | Tstruct of name (** structured value type name *) | TVar of string (** type variable (ie. C++ template variables) *) | Tarray of t * IntLit.t option * IntLit.t option (** array type with statically fixed stride and length *) [@@deriving compare] and name = | CStruct of QualifiedCppName.t | CUnion of QualifiedCppName.t (* qualified name does NOT contain template arguments of the class. It will contain template args of its parent classes, for example: MyClass::InnerClass will store "MyClass", "InnerClass" *) | CppClass of QualifiedCppName.t * template_spec_info | JavaClass of Mangled.t | ObjcClass of QualifiedCppName.t | ObjcProtocol of QualifiedCppName.t [@@deriving compare] and template_arg = TType of t | TInt of Int64.t | TNull | TNullPtr | TOpaque [@@deriving compare] and template_spec_info = | NoTemplate | Template of { mangled: string option (** WARNING: because of type substitutions performed by [sub_type] and [sub_tname], mangling is not guaranteed to be unique to a single type. All the information in the template arguments is also needed for uniqueness. *) ; args: template_arg list } [@@deriving compare] val mk : ?default:t -> ?quals:type_quals -> desc -> t (** Create Typ.t from given desc. if [default] is passed then use its value to set other fields such as quals *) val void_star : t (** void* type *) (** Stores information about type substitution *) type type_subst_t [@@deriving compare] module Name : sig (** Named types. *) type t = name [@@deriving compare] val equal : t -> t -> bool (** Equality for typenames *) val to_string : t -> string (** convert the typename to a string *) val pp : Format.formatter -> t -> unit val is_class : t -> bool (** [is_class name] holds if [name] names CPP/Objc/Java class *) val is_same_type : t -> t -> bool (** [is_class name1 name2] holds if [name1] and [name2] name same kind of type *) val name : t -> string (** name of the typename without qualifier *) val qual_name : t -> QualifiedCppName.t (** qualified name of the type, may return nonsense for Java classes *) val unqualified_name : t -> QualifiedCppName.t module C : sig val from_string : string -> t val from_qual_name : QualifiedCppName.t -> t val union_from_qual_name : QualifiedCppName.t -> t end module Java : sig val from_string : string -> t (** Create a typename from a Java classname in the form "package.class" *) val from_package_class : string -> string -> t (** Create a typename from a package name and a class name *) val is_class : t -> bool (** [is_class name] holds if [name] names a Java class *) val java_lang_object : t val java_io_serializable : t val java_lang_cloneable : t end module Cpp : sig val from_qual_name : template_spec_info -> QualifiedCppName.t -> t (** Create a typename from a C++ classname *) val is_class : t -> bool (** [is_class name] holds if [name] names a C++ class *) end module Objc : sig val from_string : string -> t (** Create a typename from a Objc classname *) val from_qual_name : QualifiedCppName.t -> t val protocol_from_qual_name : QualifiedCppName.t -> t val is_class : t -> bool (** [is_class name] holds if [name] names a Objc class *) end module Set : Caml.Set.S with type elt = t end val equal : t -> t -> bool (** Equality for types. *) val equal_desc : desc -> desc -> bool val equal_quals : type_quals -> type_quals -> bool val sub_type : type_subst_t -> t -> t val sub_tname : type_subst_t -> Name.t -> Name.t val is_type_subst_empty : type_subst_t -> bool (** Sets of types. *) module Set : Caml.Set.S with type elt = t (** Maps with type keys. *) module Map : Caml.Map.S with type key = t module Tbl : Caml.Hashtbl.S with type key = t val pp_full : Pp.env -> F.formatter -> t -> unit (** Pretty print a type with all the details. *) val pp : Pp.env -> F.formatter -> t -> unit (** Pretty print a type. *) val to_string : t -> string val d_full : t -> unit (** Dump a type with all the details. *) val d_list : t list -> unit (** Dump a list of types. *) val name : t -> Name.t option (** The name of a type *) val strip_ptr : t -> t (** turn a *T into a T. fails if [t] is not a pointer type *) val array_elem : t option -> t -> t (** If an array type, return the type of the element. If not, return the default type if given, otherwise raise an exception *) val is_objc_class : t -> bool val is_cpp_class : t -> bool val is_java_class : t -> bool val is_array_of_cpp_class : t -> bool val is_pointer_to_cpp_class : t -> bool val has_block_prefix : string -> bool val is_block_type : t -> bool (** Check if type is a type for a block in objc *) val unsome : string -> t option -> t type typ = t module Procname : sig (** Module for Procedure Names. *) (** Type of java procedure names. *) type java (** Type of c procedure names. *) type c = private { name: QualifiedCppName.t ; mangled: string option ; template_args: template_spec_info ; is_generic_model: bool } type objc_cpp_method_kind = | CPPMethod of string option (** with mangling *) | CPPConstructor of (string option * bool) (** with mangling + is it constexpr? *) | CPPDestructor of string option (** with mangling *) | ObjCClassMethod | ObjCInstanceMethod | ObjCInternalMethod (** Type of Objective C and C++ procedure names. *) type objc_cpp = private { method_name: string ; class_name: Name.t ; kind: objc_cpp_method_kind ; template_args: template_spec_info ; is_generic_model: bool } (** Type of Objective C block names. *) type block_name (** Type of procedure names. WithBlockParameters is used for creating an instantiation of a method that contains block parameters and it's called with concrete blocks. For example: foo(Block block) {block();} bar() {foo(my_block)} is executed as foo_my_block() {my_block(); } where foo_my_block is created with WithBlockParameters (foo, [my_block]) *) type t = | Java of java | C of c | Linters_dummy_method | Block of block_name | ObjC_Cpp of objc_cpp | WithBlockParameters of t * block_name list [@@deriving compare] val block_from_string : string -> block_name val block_name_of_procname : t -> block_name val equal : t -> t -> bool val hash : t -> int val sexp_of_t : t -> Sexp.t type java_type = string option * string type method_kind = | Non_Static (** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *) | Static (** in Java, procedures called with invokestatic *) (** Hash tables with proc names as keys. *) module Hashable : Caml.Hashtbl.HashedType with type t = t module Hash : Caml.Hashtbl.S with type key = t (** Maps from proc names. *) module Map : PrettyPrintable.PPMap with type key = t (** Sets of proc names. *) module Set : PrettyPrintable.PPSet with type elt = t val c : QualifiedCppName.t -> string -> template_spec_info -> is_generic_model:bool -> c (** Create a C procedure name from plain and mangled name. *) val empty_block : t (** Empty block name. *) val from_string_c_fun : string -> t (** Convert a string to a proc name. *) val get_language : t -> Config.language (** Return the language of the procedure. *) val get_method : t -> string (** Return the method/function of a procname. *) val is_objc_block : t -> bool (** Return whether the procname is a block procname. *) val is_with_block_parameters : t -> bool (** Return whether the procname is a procname instantiated with block parameters. *) val is_cpp_lambda : t -> bool (** Return whether the procname is a cpp lambda. *) val hash_pname : t -> int (** Hash function for procname. *) val is_anonymous_inner_class_name : Name.t -> bool (** Check if a class string is an anoynmous inner class name. *) val is_c_method : t -> bool (** Check if this is an Objective-C/C++ method name. *) val is_c_function : t -> bool (** Check if this is a C function name. *) val is_obj_c_pp : t -> bool (** Check if this is an Objective-C/C++ method name or C-style function. *) val is_objc_constructor : string -> bool (** Check if this is a constructor method in Objective-C. *) val is_objc_method : t -> bool (** Check if this is an Objective-C method. *) val is_constructor : t -> bool (** Check if this is a constructor. *) val is_constexpr : t -> bool (** Check if this is a constexpr function. *) val is_java : t -> bool (** Check if this is a Java procedure name. *) val is_objc_dealloc : string -> bool (** Check if this is a dealloc method in Objective-C. *) val is_destructor : t -> bool (** Check if this is a dealloc method. *) val java : Name.t -> java_type option -> string -> java_type list -> method_kind -> java (** Create a Java procedure name from its class_name method_name args_type_name return_type_name method_kind. *) val java_replace_parameters : java -> java_type list -> java (** Replace the parameters of a java procname. *) val java_replace_return_type : java -> java_type -> java (** Replace the method of a java procname. *) val mangled_objc_block : string -> t (** Create an objc block name. *) val objc_cpp : Name.t -> string -> objc_cpp_method_kind -> template_spec_info -> is_generic_model:bool -> objc_cpp (** Create an objc procedure name from a class_name and method_name. *) val with_block_parameters : t -> block_name list -> t (** Create a procedure name instantiated with block parameters from a base procedure name and a list of block procedure names (the arguments). *) val objc_cpp_get_class_name : objc_cpp -> string (** Get the class name of a Objective-C/C++ procedure name. *) val objc_cpp_get_class_type_name : objc_cpp -> Name.t val objc_cpp_replace_method_name : t -> string -> t val objc_method_kind_of_bool : bool -> objc_cpp_method_kind (** Create ObjC method type from a bool is_instance. *) val java_get_class_name : java -> string (** Return the class name of a java procedure name. *) val java_get_class_type_name : java -> Name.t (** Return the class name as a typename of a java procedure name. *) val java_get_simple_class_name : java -> string (** Return the simple class name of a java procedure name. *) val java_get_package : java -> string option (** Return the package name of a java procedure name. *) val java_get_method : java -> string (** Return the method name of a java procedure name. *) val java_get_return_type : java -> string (** Return the return type of a java procedure name. *) val java_get_parameters : java -> java_type list (** Return the parameters of a java procedure name. *) val java_get_parameters_as_strings : java -> string list (** Return the parameters of a java procname as strings. *) val java_is_access_method : t -> bool (** Check if the procedure name is an acess method (e.g. access$100 used to access private members from a nested class. *) val java_is_autogen_method : t -> bool (** Check if the procedure name is of an auto-generated method containing '$'. *) val java_is_anonymous_inner_class : t -> bool (** Check if the procedure belongs to an anonymous inner class. *) val java_is_anonymous_inner_class_constructor : t -> bool (** Check if the procedure name is an anonymous inner class constructor. *) val java_is_close : t -> bool (** Check if the method name is "close". *) val java_is_static : t -> bool (** Check if the java procedure is static. *) val java_is_vararg : t -> bool (** Check if the proc name has the type of a java vararg. Note: currently only checks that the last argument has type Object[]. *) val java_is_lambda : t -> bool (** Check if the proc name comes from a lambda expression *) val java_is_generated : t -> bool (** Check if the proc name comes from generated code *) val java_remove_hidden_inner_class_parameter : t -> t option (** Check if the last parameter is a hidden inner class, and remove it if present. This is used in private constructors, where a proxy constructor is generated with an extra parameter and calls the normal constructor. *) val java_replace_method : java -> string -> java (** Replace the method name of an existing java procname. *) val java_type_to_string : java_type -> string (** Convert a java type to a string. *) val is_class_initializer : t -> bool (** Check if this is a class initializer. *) val is_infer_undefined : t -> bool (** Check if this is a special Infer undefined procedure. *) val get_global_name_of_initializer : t -> string option (** Return the name of the global for which this procedure is the initializer if this is an initializer, None otherwise. *) val pp : Format.formatter -> t -> unit (** Pretty print a proc name. *) val pp_set : Format.formatter -> Set.t -> unit (** Pretty print a set of proc names. *) val replace_class : t -> Name.t -> t (** Replace the class name component of a procedure name. In case of Java, replace package and class name. *) val split_classname : string -> string option * string (** Given a package.class_name string, look for the latest dot and split the string in two (package, class_name). *) val to_string : t -> string (** Convert a proc name to a string for the user to see. *) val to_simplified_string : ?withclass:bool -> t -> string (** Convert a proc name into a easy string for the user to see in an IDE. *) val to_unique_id : t -> string (** Convert a proc name into a unique identifier. *) val to_filename : ?crc_only:bool -> t -> string (** Convert a proc name to a filename or only to its crc. *) val get_qualifiers : t -> QualifiedCppName.t (** get qualifiers of C/objc/C++ method/function *) val objc_cpp_get_class_qualifiers : objc_cpp -> QualifiedCppName.t (** get qualifiers of a class owning objc/C++ method *) val get_template_args_mapping : t -> t -> type_subst_t option (** Return type substitution that would produce concrete procname from generic procname. Returns None if such substitution doesn't exist NOTE: this function doesn't check if such substitution is correct in terms of return type/function parameters. NOTE: this function doesn't deal with nested template classes, it only extracts mapping for function and/or direct parent (class that defines the method) if it exists. *) end val java_proc_return_typ : Procname.java -> t (** Return the return type of [pname_java]. *) module Fieldname : sig (** Names for fields of class/struct/union *) type t [@@deriving compare] val equal : t -> t -> bool (** Equality for field names. *) (** Set for fieldnames *) module Set : Caml.Set.S with type elt = t (** Map for fieldnames *) module Map : Caml.Map.S with type key = t module Clang : sig val from_class_name : Name.t -> string -> t end module Java : sig val from_string : string -> t (** Create a java field name from string *) val is_captured_parameter : t -> bool (** Check if field is a captured parameter *) end val to_string : t -> string (** Convert a field name to a string. *) val to_full_string : t -> string val class_name_replace : t -> f:(Name.t -> Name.t) -> t val to_simplified_string : t -> string (** Convert a fieldname to a simplified string with at most one-level path. *) val to_flat_string : t -> string (** Convert a fieldname to a flat string without path. *) val pp : Format.formatter -> t -> unit (** Pretty print a field name. *) val java_get_class : t -> string (** The class part of the fieldname *) val java_get_field : t -> string (** The last component of the fieldname *) val java_is_outer_instance : t -> bool (** Check if the field is the synthetic this$n of a nested class, used to access the n-th outher instance. *) val clang_get_qual_class : t -> QualifiedCppName.t option (** get qualified classname of a field if it's coming from clang frontend. returns None otherwise *) end module Struct : sig type field = Fieldname.t * typ * Annot.Item.t [@@deriving compare] type fields = field list (** Type for a structured value. *) type t = private { fields: fields (** non-static fields *) ; statics: fields (** static fields *) ; supers: Name.t list (** supers *) ; methods: Procname.t list (** methods defined *) ; annots: Annot.Item.t (** annotations *) } type lookup = Name.t -> t option val pp_field : Pp.env -> F.formatter -> field -> unit val pp : Pp.env -> Name.t -> F.formatter -> t -> unit (** Pretty print a struct type. *) val internal_mk_struct : ?default:t -> ?fields:fields -> ?statics:fields -> ?methods:Procname.t list -> ?supers:Name.t list -> ?annots:Annot.Item.t -> unit -> t (** Construct a struct_typ, normalizing field types *) val get_extensible_array_element_typ : lookup:lookup -> typ -> typ option (** the element typ of the final extensible array in the given typ, if any *) val fld_typ : lookup:lookup -> default:typ -> Fieldname.t -> typ -> typ (** If a struct type with field f, return the type of f. If not, return the default type if given, otherwise raise an exception *) val get_field_type_and_annotation : lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option (** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *) end