[frontend] Add is_union field to CppClass

Summary:
When a union type has a member function in C++, it is parsed as `CppClass`.  However, sometimes we may want
to distinguish normal cpp classes and union classes.  This diff adds a field to the type name.

Reviewed By: jvillard

Differential Revision: D26125619

fbshipit-source-id: 44a6e8192
master
Sungkeun Cho 4 years ago committed by Facebook GitHub Bot
parent 89c8e25deb
commit e06f1e401f

@ -39,10 +39,11 @@ let lookup tenv name : Struct.t option =
with Caml.Not_found -> ( with Caml.Not_found -> (
(* ToDo: remove the following additional lookups once C/C++ interop is resolved *) (* ToDo: remove the following additional lookups once C/C++ interop is resolved *)
match (name : Typ.Name.t) with match (name : Typ.Name.t) with
| CStruct m -> ( | CStruct m ->
try Some (TypenameHash.find tenv (CppClass (m, NoTemplate))) with Caml.Not_found -> None ) TypenameHash.find_opt tenv
| CppClass (m, NoTemplate) -> ( (CppClass {name= m; template_spec_info= NoTemplate; is_union= false})
try Some (TypenameHash.find tenv (CStruct m)) with Caml.Not_found -> None ) | CppClass {name= m; template_spec_info= NoTemplate} ->
TypenameHash.find_opt tenv (CStruct m)
| _ -> | _ ->
None ) None )

@ -182,7 +182,10 @@ module T = struct
and name = and name =
| CStruct of QualifiedCppName.t | CStruct of QualifiedCppName.t
| CUnion of QualifiedCppName.t | CUnion of QualifiedCppName.t
| CppClass of QualifiedCppName.t * template_spec_info | CppClass of
{ name: QualifiedCppName.t
; template_spec_info: template_spec_info
; is_union: bool [@compare.ignore] }
| JavaClass of JavaClassName.t | JavaClass of JavaClassName.t
| ObjcClass of QualifiedCppName.t * name list | ObjcClass of QualifiedCppName.t * name list
| ObjcProtocol of QualifiedCppName.t | ObjcProtocol of QualifiedCppName.t
@ -306,8 +309,8 @@ and pp_name_c_syntax pe f = function
QualifiedCppName.pp f name QualifiedCppName.pp f name
| ObjcClass (name, protocol_names) -> | ObjcClass (name, protocol_names) ->
F.fprintf f "%a%a" QualifiedCppName.pp name (pp_protocols pe) protocol_names F.fprintf f "%a%a" QualifiedCppName.pp name (pp_protocols pe) protocol_names
| CppClass (name, template_spec) -> | CppClass {name; template_spec_info} ->
F.fprintf f "%a%a" QualifiedCppName.pp name (pp_template_spec_info pe) template_spec F.fprintf f "%a%a" QualifiedCppName.pp name (pp_template_spec_info pe) template_spec_info
| JavaClass name -> | JavaClass name ->
JavaClassName.pp f name JavaClassName.pp f name
@ -362,8 +365,8 @@ module Name = struct
that, we can use these loosened compare functions instead. *) that, we can use these loosened compare functions instead. *)
let loose_compare x y = let loose_compare x y =
match (x, y) with match (x, y) with
| (CStruct name1 | CppClass (name1, NoTemplate)), (CStruct name2 | CppClass (name2, NoTemplate)) | ( (CStruct name1 | CppClass {name= name1; template_spec_info= NoTemplate})
-> , (CStruct name2 | CppClass {name= name2; template_spec_info= NoTemplate}) ) ->
QualifiedCppName.compare name1 name2 QualifiedCppName.compare name1 name2
| _ -> | _ ->
compare x y compare x y
@ -377,8 +380,8 @@ module Name = struct
| ObjcClass (name, protocol_names) -> | ObjcClass (name, protocol_names) ->
let protocols = F.asprintf "%a" (pp_protocols Pp.text) protocol_names in let protocols = F.asprintf "%a" (pp_protocols Pp.text) protocol_names in
QualifiedCppName.append_protocols name ~protocols QualifiedCppName.append_protocols name ~protocols
| CppClass (name, templ_args) -> | CppClass {name; template_spec_info} ->
let template_suffix = F.asprintf "%a" (pp_template_spec_info Pp.text) templ_args in let template_suffix = F.asprintf "%a" (pp_template_spec_info Pp.text) template_spec_info in
QualifiedCppName.append_template_args_to_last name ~args:template_suffix QualifiedCppName.append_template_args_to_last name ~args:template_suffix
| JavaClass _ -> | JavaClass _ ->
QualifiedCppName.empty QualifiedCppName.empty
@ -387,13 +390,18 @@ module Name = struct
let unqualified_name = function let unqualified_name = function
| CStruct name | CUnion name | ObjcProtocol name | ObjcClass (name, _) -> | CStruct name | CUnion name | ObjcProtocol name | ObjcClass (name, _) ->
name name
| CppClass (name, _) -> | CppClass {name} ->
name name
| JavaClass _ -> | JavaClass _ ->
QualifiedCppName.empty QualifiedCppName.empty
let get_template_spec_info = function CppClass (_, templ_args) -> Some templ_args | _ -> None let get_template_spec_info = function
| CppClass {template_spec_info} ->
Some template_spec_info
| _ ->
None
let name n = let name n =
match n with match n with
@ -479,7 +487,9 @@ module Name = struct
end end
module Cpp = struct module Cpp = struct
let from_qual_name template_spec_info qual_name = CppClass (qual_name, template_spec_info) let from_qual_name template_spec_info ~is_union qual_name =
CppClass {name= qual_name; template_spec_info; is_union}
let is_class = function CppClass _ -> true | _ -> false let is_class = function CppClass _ -> true | _ -> false
end end

@ -102,14 +102,13 @@ and desc =
and name = and name =
| CStruct of QualifiedCppName.t | CStruct of QualifiedCppName.t
| CUnion of QualifiedCppName.t | CUnion of QualifiedCppName.t
(* qualified name does NOT contain template arguments of the class. It will contain template (** qualified name does NOT contain template arguments of the class. It will contain template
args of its parent classes, for example: MyClass<int>::InnerClass<int> will store args of its parent classes, for example: MyClass<int>::InnerClass<int> will store
"MyClass<int>", "InnerClass" *) "MyClass<int>", "InnerClass" *)
| CppClass of QualifiedCppName.t * template_spec_info | CppClass of {name: QualifiedCppName.t; template_spec_info: template_spec_info; is_union: bool}
| JavaClass of JavaClassName.t | JavaClass of JavaClassName.t
| ObjcClass of QualifiedCppName.t * name list | ObjcClass of QualifiedCppName.t * name list
(* ObjC class that conforms to a list of protocols, (** ObjC class that conforms to a list of protocols, e.g. id<NSFastEnumeration, NSCopying> *)
e.g. id<NSFastEnumeration, NSCopying> *)
| ObjcProtocol of QualifiedCppName.t | ObjcProtocol of QualifiedCppName.t
and template_arg = TType of t | TInt of Int64.t | TNull | TNullPtr | TOpaque and template_arg = TType of t | TInt of Int64.t | TNull | TNullPtr | TOpaque
@ -215,7 +214,7 @@ module Name : sig
end end
module Cpp : sig module Cpp : sig
val from_qual_name : template_spec_info -> QualifiedCppName.t -> t val from_qual_name : template_spec_info -> is_union:bool -> QualifiedCppName.t -> t
(** Create a typename from a C++ classname *) (** Create a typename from a C++ classname *)
val is_class : t -> bool val is_class : t -> bool

@ -380,8 +380,8 @@ let runs_on_ui_thread tenv pname =
let is_recursive_lock_type = function let is_recursive_lock_type = function
| Typ.CppClass (qname, _) -> | Typ.CppClass {name} ->
Clang.is_recursive_lock_type qname Clang.is_recursive_lock_type name
| _ -> | _ ->
(* non-C++ lock types are always considered recursive *) (* non-C++ lock types are always considered recursive *)
true true

@ -48,7 +48,7 @@ let templated_name_of_class_name class_name =
| ObjcClass (qual_name, protocol_names) -> | ObjcClass (qual_name, protocol_names) ->
let protocols = F.asprintf "%a" (Typ.pp_protocols Pp.text) protocol_names in let protocols = F.asprintf "%a" (Typ.pp_protocols Pp.text) protocol_names in
(QualifiedCppName.append_protocols qual_name ~protocols, []) (QualifiedCppName.append_protocols qual_name ~protocols, [])
| CppClass (qual_name, template_spec_info) -> | CppClass {name= qual_name; template_spec_info} ->
(qual_name, template_args_of_template_spec_info template_spec_info) (qual_name, template_args_of_template_spec_info template_spec_info)
| JavaClass mangled_name -> | JavaClass mangled_name ->
(QualifiedCppName.of_list [JavaClassName.to_string mangled_name], []) (QualifiedCppName.of_list [JavaClassName.to_string mangled_name], [])

@ -279,7 +279,7 @@ let placement_new size_exp {exp= src_exp1; typ= t1} src_arg2_opt =
match (t1.Typ.desc, src_arg2_opt) with match (t1.Typ.desc, src_arg2_opt) with
| Tint _, None | Tint _, Some {typ= {Typ.desc= Tint _}} -> | Tint _, None | Tint _, Some {typ= {Typ.desc= Tint _}} ->
malloc ~can_be_zero:true (Exp.BinOp (Binop.PlusA (Some Typ.size_t), size_exp, src_exp1)) malloc ~can_be_zero:true (Exp.BinOp (Binop.PlusA (Some Typ.size_t), size_exp, src_exp1))
| Tstruct (CppClass (name, _)), None | Tstruct (CppClass {name}), None
when [%compare.equal: string list] (QualifiedCppName.to_list name) ["std"; "nothrow_t"] -> when [%compare.equal: string list] (QualifiedCppName.to_list name) ["std"; "nothrow_t"] ->
malloc ~can_be_zero:true size_exp malloc ~can_be_zero:true size_exp
| _, _ -> | _, _ ->
@ -668,7 +668,11 @@ end
module Split = struct module Split = struct
let std_vector model_env ~adds_at_least_one ({typ= vector_typ} as vec_arg) mem = let std_vector model_env ~adds_at_least_one ({typ= vector_typ} as vec_arg) mem =
match vector_typ with match vector_typ with
| Typ.{desc= Tptr ({desc= Tstruct (CppClass (_, Template {args= TType elt_typ :: _}))}, _)} -> | Typ.
{ desc=
Tptr
( {desc= Tstruct (CppClass {template_spec_info= Template {args= TType elt_typ :: _}})}
, _ ) } ->
let arr_locs = StdVector.deref_of model_env elt_typ vec_arg mem in let arr_locs = StdVector.deref_of model_env elt_typ vec_arg mem in
let size = if adds_at_least_one then Dom.Val.Itv.pos else Dom.Val.Itv.nat in let size = if adds_at_least_one then Dom.Val.Itv.pos else Dom.Val.Itv.nat in
StdVector.set_size model_env arr_locs size mem StdVector.set_size model_env arr_locs size mem

@ -299,7 +299,7 @@ let create_c_record_typename (tag_kind : Clang_ast_t.tag_kind) =
| `TTK_Union -> | `TTK_Union ->
Typ.Name.C.union_from_qual_name Typ.Name.C.union_from_qual_name
| `TTK_Class -> | `TTK_Class ->
Typ.Name.Cpp.from_qual_name Typ.NoTemplate Typ.Name.Cpp.from_qual_name Typ.NoTemplate ~is_union:false
let get_class_template_name = function let get_class_template_name = function
@ -449,10 +449,12 @@ and get_record_friend_decl_type tenv definition_decl =
and get_record_typename ?tenv decl = and get_record_typename ?tenv decl =
let open Clang_ast_t in let open Clang_ast_t in
let linters_mode = match tenv with Some _ -> false | None -> true in let linters_mode = match tenv with Some _ -> false | None -> true in
let is_union_tag tag_kind = match tag_kind with `TTK_Union -> true | _ -> false in
match (decl, tenv) with match (decl, tenv) with
| RecordDecl (_, name_info, _, _, _, tag_kind, _), _ -> | RecordDecl (_, name_info, _, _, _, tag_kind, _), _ ->
CAst_utils.get_qualified_name ~linters_mode name_info |> create_c_record_typename tag_kind CAst_utils.get_qualified_name ~linters_mode name_info |> create_c_record_typename tag_kind
| ClassTemplateSpecializationDecl (_, _, _, _, _, _, _, _, mangling, spec_info), Some tenv -> | ClassTemplateSpecializationDecl (_, _, _, _, _, tag_kind, _, _, mangling, spec_info), Some tenv
->
let tname = let tname =
match CAst_utils.get_decl spec_info.tsi_template_decl with match CAst_utils.get_decl spec_info.tsi_template_decl with
| Some dec -> | Some dec ->
@ -462,15 +464,17 @@ and get_record_typename ?tenv decl =
in in
let args = get_template_args tenv spec_info in let args = get_template_args tenv spec_info in
let mangled = if String.equal "" mangling then None else Some mangling in let mangled = if String.equal "" mangling then None else Some mangling in
Typ.Name.Cpp.from_qual_name (Typ.Template {mangled; args}) tname Typ.Name.Cpp.from_qual_name
(Typ.Template {mangled; args})
~is_union:(is_union_tag tag_kind) tname
| CXXRecordDecl (_, name_info, _, _, _, `TTK_Union, _, _), _ -> | CXXRecordDecl (_, name_info, _, _, _, `TTK_Union, _, _), _ ->
Typ.CUnion (CAst_utils.get_qualified_name ~linters_mode name_info) Typ.CUnion (CAst_utils.get_qualified_name ~linters_mode name_info)
| CXXRecordDecl (_, name_info, _, _, _, _, _, _), _ | CXXRecordDecl (_, name_info, _, _, _, tag_kind, _, _), _
| ClassTemplatePartialSpecializationDecl (_, name_info, _, _, _, _, _, _, _, _), _ | ClassTemplatePartialSpecializationDecl (_, name_info, _, _, _, tag_kind, _, _, _, _), _
| ClassTemplateSpecializationDecl (_, name_info, _, _, _, _, _, _, _, _), _ -> | ClassTemplateSpecializationDecl (_, name_info, _, _, _, tag_kind, _, _, _, _), _ ->
(* we use Typ.CppClass for C++ because we expect Typ.CppClass from *) (* we use Typ.CppClass for C++ because we expect Typ.CppClass from *)
(* types that have methods. And in C++ struct/class/union can have methods *) (* types that have methods. And in C++ struct/class/union can have methods *)
Typ.Name.Cpp.from_qual_name Typ.NoTemplate Typ.Name.Cpp.from_qual_name Typ.NoTemplate ~is_union:(is_union_tag tag_kind)
(CAst_utils.get_qualified_name ~linters_mode name_info) (CAst_utils.get_qualified_name ~linters_mode name_info)
| ObjCInterfaceDecl (_, name_info, _, _, _), _ | ObjCImplementationDecl (_, name_info, _, _, _), _ | ObjCInterfaceDecl (_, name_info, _, _, _), _ | ObjCImplementationDecl (_, name_info, _, _, _), _
-> ->

@ -586,7 +586,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
builtin_pname builtin_pname
| None -> | None ->
let class_typename = let class_typename =
Typ.Name.Cpp.from_qual_name Typ.NoTemplate Typ.Name.Cpp.from_qual_name Typ.NoTemplate ~is_union:false
(CAst_utils.get_class_name_from_member name_info) (CAst_utils.get_class_name_from_member name_info)
in in
if is_inner_destructor then if is_inner_destructor then
@ -3791,7 +3791,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact}, void_typ) (Exp.Sizeof {typ; nbytes= None; dynamic_length= None; subtype= Subtype.exact}, void_typ)
in in
let class_tname = let class_tname =
Typ.Name.Cpp.from_qual_name Typ.NoTemplate (QualifiedCppName.of_list ["std"; "type_info"]) Typ.Name.Cpp.from_qual_name Typ.NoTemplate ~is_union:false
(QualifiedCppName.of_list ["std"; "type_info"])
in in
let field_name = CGeneral_utils.mk_class_field_name class_tname "__type_name" in let field_name = CGeneral_utils.mk_class_field_name class_tname "__type_name" in
let ret_exp = Exp.Var ret_id in let ret_exp = Exp.Var ret_id in

Loading…
Cancel
Save