diff --git a/infer/src/clang/CType.ml b/infer/src/clang/CType.ml index 412e5cd6f..9dc88f436 100644 --- a/infer/src/clang/CType.ml +++ b/infer/src/clang/CType.ml @@ -74,3 +74,86 @@ let is_reference_type {Clang_ast_t.qt_type_ptr} = true | _ -> false + + +let is_pointer_to_const {Clang_ast_t.qt_type_ptr} = + match CAst_utils.get_type qt_type_ptr with + | Some (PointerType (_, {Clang_ast_t.qt_is_const})) + | Some (ObjCObjectPointerType (_, {Clang_ast_t.qt_is_const})) + | Some (RValueReferenceType (_, {Clang_ast_t.qt_is_const})) + | Some (LValueReferenceType (_, {Clang_ast_t.qt_is_const})) -> + qt_is_const + | _ -> + false + + +let is_value {Clang_ast_t.qt_type_ptr} = + match qt_type_ptr with + | Clang_ast_extend.Builtin _ + (* We rely on the assumption here that Clang_ast_extend.ReferenceOf is only created for pass-by-value structs. *) + (* TODO: Create a dedicated variant in Clang_ast_extend for pass-by-val params *) + | Clang_ast_extend.ReferenceOf _ -> + true + | Clang_ast_types.TypePtr.Ptr _ -> + let rec is_value_raw qt_type_ptr = + match CAst_utils.get_type qt_type_ptr with + | Some (BuiltinType _) + | Some (ComplexType _) + | Some (DependentSizedExtVectorType _) + | Some (VectorType _) + | Some (ExtVectorType _) + | Some (RecordType _) + | Some (EnumType _) + | Some (InjectedClassNameType _) + | Some (ObjCObjectType _) + | Some (ObjCInterfaceType _) -> + true + | Some (AdjustedType (_, {Clang_ast_t.qt_type_ptr})) + | Some (DecayedType (_, {Clang_ast_t.qt_type_ptr})) + | Some (ParenType (_, {Clang_ast_t.qt_type_ptr})) + | Some (DecltypeType (_, {Clang_ast_t.qt_type_ptr})) + | Some (AtomicType (_, {Clang_ast_t.qt_type_ptr})) -> + is_value_raw qt_type_ptr + | Some (TypedefType (_, {Clang_ast_t.tti_child_type})) -> + is_value_raw tti_child_type.Clang_ast_t.qt_type_ptr + (* These types could be value types, and we try our best to resolve them *) + | Some (AttributedType ({Clang_ast_t.ti_desugared_type}, _)) + | Some (TypeOfExprType {Clang_ast_t.ti_desugared_type}) + | Some (TypeOfType {Clang_ast_t.ti_desugared_type}) + | Some (UnaryTransformType {Clang_ast_t.ti_desugared_type}) + | Some (ElaboratedType {Clang_ast_t.ti_desugared_type}) + | Some (AutoType {Clang_ast_t.ti_desugared_type}) + | Some (DependentNameType {Clang_ast_t.ti_desugared_type}) + | Some (DeducedTemplateSpecializationType {Clang_ast_t.ti_desugared_type}) + | Some (TemplateSpecializationType {Clang_ast_t.ti_desugared_type}) + | Some (DependentTemplateSpecializationType {Clang_ast_t.ti_desugared_type}) + | Some (TemplateTypeParmType {Clang_ast_t.ti_desugared_type}) + | Some (SubstTemplateTypeParmType {Clang_ast_t.ti_desugared_type}) + | Some (SubstTemplateTypeParmPackType {Clang_ast_t.ti_desugared_type}) + | Some (PackExpansionType {Clang_ast_t.ti_desugared_type}) + | Some (UnresolvedUsingType {Clang_ast_t.ti_desugared_type}) -> ( + match ti_desugared_type with Some ptr -> is_value_raw ptr | None -> false ) + (* These types are known to be non-value types *) + | Some (PointerType _) + | Some (BlockPointerType _) + | Some (LValueReferenceType _) + | Some (RValueReferenceType _) + | Some (MemberPointerType _) + | Some (ConstantArrayType _) + | Some (IncompleteArrayType _) + | Some (VariableArrayType _) + | Some (DependentSizedArrayType _) + | Some (FunctionProtoType _) + | Some (FunctionNoProtoType _) + | Some (ObjCObjectPointerType _) + | Some (NoneType _) + | Some (DependentAddressSpaceType _) + (* These types I don't know what they are. Be conservative and treat them as non value types *) + | Some (ObjCTypeParamType _) + | Some (PipeType _) + | None -> + false + in + is_value_raw qt_type_ptr + | _ -> + false diff --git a/infer/src/clang/CType.mli b/infer/src/clang/CType.mli index 939df8af8..f14744fc3 100644 --- a/infer/src/clang/CType.mli +++ b/infer/src/clang/CType.mli @@ -22,3 +22,7 @@ val return_type_of_function_type : Clang_ast_t.qual_type -> Clang_ast_t.qual_typ val is_block_type : Clang_ast_t.qual_type -> bool val is_reference_type : Clang_ast_t.qual_type -> bool + +val is_pointer_to_const : Clang_ast_t.qual_type -> bool + +val is_value : Clang_ast_t.qual_type -> bool diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index c5b0a53cb..51519f61d 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -410,89 +410,6 @@ let sil_method_annotation_of_args args method_type : Annot.Method.t = (retval_annot, param_annots) -let is_pointer_to_const {Clang_ast_t.qt_type_ptr} = - match CAst_utils.get_type qt_type_ptr with - | Some (PointerType (_, {Clang_ast_t.qt_is_const})) - | Some (ObjCObjectPointerType (_, {Clang_ast_t.qt_is_const})) - | Some (RValueReferenceType (_, {Clang_ast_t.qt_is_const})) - | Some (LValueReferenceType (_, {Clang_ast_t.qt_is_const})) -> - qt_is_const - | _ -> - false - - -let is_value {Clang_ast_t.qt_type_ptr} = - match qt_type_ptr with - | Clang_ast_extend.Builtin _ - (* We rely on the assumption here that Clang_ast_extend.ReferenceOf is only created for pass-by-value structs. *) - (* TODO: Create a dedicated variant in Clang_ast_extend for pass-by-val params *) - | Clang_ast_extend.ReferenceOf _ -> - true - | Clang_ast_types.TypePtr.Ptr _ -> - let rec is_value_raw qt_type_ptr = - match CAst_utils.get_type qt_type_ptr with - | Some (BuiltinType _) - | Some (ComplexType _) - | Some (DependentSizedExtVectorType _) - | Some (VectorType _) - | Some (ExtVectorType _) - | Some (RecordType _) - | Some (EnumType _) - | Some (InjectedClassNameType _) - | Some (ObjCObjectType _) - | Some (ObjCInterfaceType _) -> - true - | Some (AdjustedType (_, {Clang_ast_t.qt_type_ptr})) - | Some (DecayedType (_, {Clang_ast_t.qt_type_ptr})) - | Some (ParenType (_, {Clang_ast_t.qt_type_ptr})) - | Some (DecltypeType (_, {Clang_ast_t.qt_type_ptr})) - | Some (AtomicType (_, {Clang_ast_t.qt_type_ptr})) -> - is_value_raw qt_type_ptr - | Some (TypedefType (_, {Clang_ast_t.tti_child_type})) -> - is_value_raw tti_child_type.Clang_ast_t.qt_type_ptr - (* These types could be value types, and we try our best to resolve them *) - | Some (AttributedType ({Clang_ast_t.ti_desugared_type}, _)) - | Some (TypeOfExprType {Clang_ast_t.ti_desugared_type}) - | Some (TypeOfType {Clang_ast_t.ti_desugared_type}) - | Some (UnaryTransformType {Clang_ast_t.ti_desugared_type}) - | Some (ElaboratedType {Clang_ast_t.ti_desugared_type}) - | Some (AutoType {Clang_ast_t.ti_desugared_type}) - | Some (DependentNameType {Clang_ast_t.ti_desugared_type}) - | Some (DeducedTemplateSpecializationType {Clang_ast_t.ti_desugared_type}) - | Some (TemplateSpecializationType {Clang_ast_t.ti_desugared_type}) - | Some (DependentTemplateSpecializationType {Clang_ast_t.ti_desugared_type}) - | Some (TemplateTypeParmType {Clang_ast_t.ti_desugared_type}) - | Some (SubstTemplateTypeParmType {Clang_ast_t.ti_desugared_type}) - | Some (SubstTemplateTypeParmPackType {Clang_ast_t.ti_desugared_type}) - | Some (PackExpansionType {Clang_ast_t.ti_desugared_type}) - | Some (UnresolvedUsingType {Clang_ast_t.ti_desugared_type}) -> ( - match ti_desugared_type with Some ptr -> is_value_raw ptr | None -> false ) - (* These types are known to be non-value types *) - | Some (PointerType _) - | Some (BlockPointerType _) - | Some (LValueReferenceType _) - | Some (RValueReferenceType _) - | Some (MemberPointerType _) - | Some (ConstantArrayType _) - | Some (IncompleteArrayType _) - | Some (VariableArrayType _) - | Some (DependentSizedArrayType _) - | Some (FunctionProtoType _) - | Some (FunctionNoProtoType _) - | Some (ObjCObjectPointerType _) - | Some (NoneType _) - | Some (DependentAddressSpaceType _) - (* These types I don't know what they are. Be conservative and treat them as non value types *) - | Some (ObjCTypeParamType _) - | Some (PipeType _) - | None -> - false - in - is_value_raw qt_type_ptr - | _ -> - false - - (** Returns a list of the indices of expressions in [args] which point to const-typed values. Each index is offset by [shift]. *) let get_const_args_indices ~shift args = @@ -502,7 +419,7 @@ let get_const_args_indices ~shift args = List.rev result | (_, qual_type) :: tl -> incr i ; - if is_pointer_to_const qual_type then aux (!i - 1 :: result) tl else aux result tl + if CType.is_pointer_to_const qual_type then aux (!i - 1 :: result) tl else aux result tl in aux [] args @@ -510,7 +427,7 @@ let get_const_args_indices ~shift args = let get_byval_args_indices ~shift args = List.filter_mapi args ~f:(fun index (_, qual_type) -> let index' = index + shift in - Option.some_if (is_value qual_type) index' ) + Option.some_if (CType.is_value qual_type) index' ) let get_objc_property_accessor tenv ms =