diff --git a/infer/lib/linter_rules/linters.al b/infer/lib/linter_rules/linters.al index 38ec963ec..b1687a3bd 100644 --- a/infer/lib/linter_rules/linters.al +++ b/infer/lib/linter_rules/linters.al @@ -81,10 +81,10 @@ DEFINE-CHECKER BAD_POINTER_COMPARISON = { DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = { LET exists_method_calling_addObserver = - call_method_strict("addObserver:selector:name:object:") HOLDS-EVENTUALLY; + call_method("addObserver:selector:name:object:") HOLDS-EVENTUALLY; LET exists_method_calling_addObserverForName = - call_method_strict("addObserverForName:object:queue:usingBlock:") HOLDS-EVENTUALLY; + call_method("addObserverForName:object:queue:usingBlock:") HOLDS-EVENTUALLY; LET add_observer = exists_method_calling_addObserver OR exists_method_calling_addObserverForName; @@ -95,10 +95,10 @@ DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = { HOLDS-EVENTUALLY; LET exists_method_calling_removeObserver = - call_method_strict("removeObserver:") HOLDS-EVENTUALLY; + call_method("removeObserver:") HOLDS-EVENTUALLY; LET exists_method_calling_removeObserverName = - call_method_strict("removeObserver:name:object:") HOLDS-EVENTUALLY; + call_method("removeObserver:name:object:") HOLDS-EVENTUALLY; LET remove_observer = exists_method_calling_removeObserver OR exists_method_calling_removeObserverName; @@ -137,11 +137,11 @@ DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = { DEFINE-CHECKER STRONG_DELEGATE_WARNING = { - LET name_contains_delegate = property_name_contains_word(REGEXP("[dD]elegate")); + LET name_contains_delegate = property_named(REGEXP("[dD]elegate")); LET name_does_not_contain_delegates = - NOT property_name_contains_word(REGEXP("[dD]elegates")); + NOT property_named(REGEXP("[dD]elegates")); LET name_does_not_contains_queue = - NOT property_name_contains_word(REGEXP("[qQ]ueue")); + NOT property_named(REGEXP("[qQ]ueue")); SET report_when = WHEN diff --git a/infer/src/clang/cAst_utils.ml b/infer/src/clang/cAst_utils.ml index 671f39dd3..5037f0d32 100644 --- a/infer/src/clang/cAst_utils.ml +++ b/infer/src/clang/cAst_utils.ml @@ -238,18 +238,6 @@ let is_const_expr_var decl = | Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr | _ -> false -let is_ptr_to_objc_class typ class_name = - match typ with - | Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) -> - (match get_desugared_type qt_type_ptr with - | Some ObjCInterfaceType (_, ptr) -> - (match get_decl ptr with - | Some ObjCInterfaceDecl (_, ndi, _, _, _) -> - String.equal ndi.ni_name class_name - | _ -> false) - | _ -> false) - | _ -> false - let full_name_of_decl_opt decl_opt = match decl_opt with | Some decl -> diff --git a/infer/src/clang/cAst_utils.mli b/infer/src/clang/cAst_utils.mli index b4cfea8f7..966e27be9 100644 --- a/infer/src/clang/cAst_utils.mli +++ b/infer/src/clang/cAst_utils.mli @@ -92,8 +92,6 @@ val is_syntactically_global_var : Clang_ast_t.decl -> bool (** true if a declaration is a constexpr variable *) val is_const_expr_var : Clang_ast_t.decl -> bool -val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool - val full_name_of_decl_opt : Clang_ast_t.decl option -> QualifiedCppName.t (** Generates a key for a statement based on its sub-statements and the statement tag. *) diff --git a/infer/src/clang/cPredicates.ml b/infer/src/clang/cPredicates.ml index 7bea6c988..22d736c25 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -63,12 +63,22 @@ type t = ALVar.formula_id * ALVar.alexp list(* (name, [param1,...,paramK]) *) (* true if and only if a substring of container matches the regular expression defined by contained *) -let str_match_regex container contained = - let rexp = Str.regexp contained in +let str_match_regex container re = + let rexp = Str.regexp re in try Str.search_forward rexp container 0 >= 0 with Not_found -> false +let compare_str_with_alexp s ae = + match ae with + | ALVar.Const s' -> + String.equal s s' + | ALVar.Regexp re -> str_match_regex s re + | _ -> + Logging.out "[WARNING]: ALVAR expression '%s' is not a constant or regexp\n" + (ALVar.alexp_to_string ae); + false + let pp_predicate fmt (_name, _arglist) = let name = ALVar.formula_id_to_string _name in let arglist = List.map ~f:ALVar.alexp_to_string _arglist in @@ -77,54 +87,34 @@ let pp_predicate fmt (_name, _arglist) = let is_declaration_kind decl s = String.equal (Clang_ast_proj.get_decl_kind_string decl) s -let _is_objc_interface_named comp an expected_name = +(* is an objc interface with name expected_name *) +let is_objc_interface_named an expected_name = match an with | Ctl_parser_types.Decl Clang_ast_t.ObjCInterfaceDecl(_, ni, _, _, _) -> - comp ni.ni_name expected_name + compare_str_with_alexp ni.ni_name expected_name | _ -> false -(* is an objc interface with name expected_name *) -let is_objc_interface_named_strict an expected_name = - _is_objc_interface_named (String.equal) an expected_name - -(* is an objc interface with name expected_name *) -let is_objc_interface_named an expected_name = - _is_objc_interface_named (str_match_regex) an expected_name - -let _is_object_of_class_named comp receiver cname = +(* checkes whether an object is of a certain class *) +let is_object_of_class_named receiver cname = let open Clang_ast_t in match receiver with | PseudoObjectExpr (_, _, ei) | ImplicitCastExpr (_, _, ei, _) | ParenExpr (_, _, ei) -> (match CAst_utils.qual_type_to_objc_interface ei.ei_qual_type with - | Some interface -> comp (Ctl_parser_types.Decl interface) cname + | Some interface -> + is_objc_interface_named (Ctl_parser_types.Decl interface) cname | _ -> false) | _ -> false -(* checkes whether an object is of a certain class *) -let is_object_of_class_named_strict receiver cname = - _is_object_of_class_named (is_objc_interface_named_strict) receiver cname - -(* checkes whether an object is of a certain class *) -let is_object_of_class_named receiver cname = - _is_object_of_class_named (is_objc_interface_named) receiver cname - -let _call_method comp an m = +(* an |= call_method(m) where the name must be exactly m *) +let call_method an m = match an with | Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, _, _, omei)) -> - comp omei.omei_selector m + compare_str_with_alexp omei.omei_selector m | _ -> false -(* an |= call_method(m) where the name must be exactly m *) -let call_method_strict an m = - _call_method (String.equal) an m - -(* an |= call_method(m) where we check is the name contains m *) -let call_method an m = - _call_method (str_match_regex) an m - -let is_receiver_kind_class comp omei cname = +let is_receiver_kind_class omei cname = let open Clang_ast_t in match omei.omei_receiver_kind with | `Class ptr -> @@ -132,48 +122,34 @@ let is_receiver_kind_class comp omei cname = | Some ObjCInterfaceType (_, ptr) -> (match CAst_utils.get_decl ptr with | Some ObjCInterfaceDecl (_, ndi, _, _, _) -> - comp ndi.ni_name cname + compare_str_with_alexp ndi.ni_name cname | _ -> false) | _ -> false) | _ -> false -let _call_class_method comp an cname mname = - match an with - | Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, _, _, omei)) -> - is_receiver_kind_class comp omei cname && - comp omei.omei_selector mname - | _ -> false - -let call_class_method_strict an cname mname = - _call_class_method (String.equal) an cname mname - let call_class_method an cname mname = - _call_class_method (str_match_regex) an cname mname - -let _call_instance_method comp an cname mname = match an with - | Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, receiver :: _, _, omei)) -> - is_object_of_class_named receiver cname && - comp omei.omei_selector mname + | Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, _, _, omei)) -> + is_receiver_kind_class omei cname && + compare_str_with_alexp omei.omei_selector mname | _ -> false -(* an is a node calling method mname of class cname. - The equality is strict. -*) -let call_instance_method_strict an cname mname = - _call_instance_method (String.equal) an cname mname - (* an is a node calling method whose name contains mname of a class whose name contains cname. *) let call_instance_method an cname mname = - _call_instance_method (str_match_regex) an cname mname + match an with + | Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, receiver :: _, _, omei)) -> + is_object_of_class_named receiver cname && + compare_str_with_alexp omei.omei_selector mname + | _ -> false -let property_name_contains_word word an = +let property_named an name = match an with | Ctl_parser_types.Decl decl -> (match Clang_ast_proj.get_named_decl_tuple decl with - | Some (_, n) -> str_match_regex n.Clang_ast_t.ni_name word + | Some (_, n) -> + compare_str_with_alexp n.Clang_ast_t.ni_name name | _ -> false) | _ -> false @@ -195,11 +171,11 @@ let decl_ref_is_in names st = | Clang_ast_t.DeclRefExpr (_, _, _, drti) -> (match drti.drti_decl_ref with | Some dr -> let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in - List.exists ~f:(String.equal ndi.ni_name) names + List.exists ~f:(compare_str_with_alexp ndi.ni_name) names | _ -> false) | _ -> false -let call_function_named names an = +let call_function_named an names = match an with | Ctl_parser_types.Stmt st -> CAst_utils.exists_eventually_st decl_ref_is_in names st @@ -291,70 +267,72 @@ let is_objc_dealloc context = let captures_cxx_references an = List.length (captured_variables_cxx_ref an) > 0 -let is_binop_with_kind str_kind an = +let is_binop_with_kind an alexp_kind = + let str_kind = ALVar.alexp_to_string alexp_kind in if not (Clang_ast_proj.is_valid_binop_kind_name str_kind) then failwith ("Binary operator kind " ^ str_kind ^ " is not valid"); match an with | Ctl_parser_types.Stmt (Clang_ast_t.BinaryOperator (_, _, _, boi)) -> - String.equal (Clang_ast_proj.string_of_binop_kind boi.boi_kind) str_kind + compare_str_with_alexp (Clang_ast_proj.string_of_binop_kind boi.boi_kind) alexp_kind | _ -> false -let is_unop_with_kind str_kind an = +let is_unop_with_kind an alexp_kind = + let str_kind = ALVar.alexp_to_string alexp_kind in if not (Clang_ast_proj.is_valid_unop_kind_name str_kind) then failwith ("Unary operator kind " ^ str_kind ^ " is not valid"); match an with | Ctl_parser_types.Stmt (Clang_ast_t.UnaryOperator (_, _, _, uoi)) -> - String.equal (Clang_ast_proj.string_of_unop_kind uoi.uoi_kind) str_kind + compare_str_with_alexp (Clang_ast_proj.string_of_unop_kind uoi.uoi_kind) alexp_kind | _ -> false -let is_node nodename an = - if not (Clang_ast_proj.is_valid_astnode_kind nodename) then - failwith ("Node " ^ nodename ^ " is not a valid AST node"); +let is_node an nodename = + let nodename_str = ALVar.alexp_to_string nodename in + if not (Clang_ast_proj.is_valid_astnode_kind nodename_str) then + failwith ("Node " ^ nodename_str ^ " is not a valid AST node"); let an_str = match an with | Ctl_parser_types.Stmt s -> Clang_ast_proj.get_stmt_kind_string s | Ctl_parser_types.Decl d -> Clang_ast_proj.get_decl_kind_string d in - String.equal nodename an_str + compare_str_with_alexp an_str nodename + +let is_ptr_to_objc_class typ class_name = + match typ with + | Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) -> + (match CAst_utils.get_desugared_type qt_type_ptr with + | Some ObjCInterfaceType (_, ptr) -> + (match CAst_utils.get_decl ptr with + | Some ObjCInterfaceDecl (_, ndi, _, _, _) -> + compare_str_with_alexp ndi.ni_name class_name + | _ -> false) + | _ -> false) + | _ -> false (* node an is of class classname *) -let isa classname an = +let isa an classname = match an with | Ctl_parser_types.Stmt stmt -> (match Clang_ast_proj.get_expr_tuple stmt with | Some (_, _, expr_info) -> let typ = CAst_utils.get_desugared_type expr_info.ei_qual_type.qt_type_ptr in - CAst_utils.is_ptr_to_objc_class typ classname + is_ptr_to_objc_class typ classname | _ -> false) | _ -> false -let _declaration_has_name comp an name = +(* an is a declaration whose name contains a regexp defined by re *) +let declaration_has_name an name = match an with | Ctl_parser_types.Decl d -> (match Clang_ast_proj.get_named_decl_tuple d with - | Some (_, ndi) -> comp ndi.ni_name name + | Some (_, ndi) -> compare_str_with_alexp ndi.ni_name name | _ -> false) | _ -> false -(* an is a declaration whose name contains a regexp defined by re *) -let declaration_has_name an re = - _declaration_has_name (str_match_regex) an re - -(* an is a declaration called precisely name *) -let declaration_has_name_strict an name = - _declaration_has_name (String.equal) an name - -let _is_class comp an re = +let is_class an re = match an with | Ctl_parser_types.Decl (Clang_ast_t.ObjCInterfaceDecl _) | Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl _) -> - _declaration_has_name comp an re + declaration_has_name an re | _ -> false -let is_class an re = - _is_class (str_match_regex) an re - -let is_class_strict an name = - _is_class (String.equal) an name - let decl_unavailable_in_supported_ios_sdk (cxt : CLintersContext.context) an = let allowed_os_versions = match Config.iphoneos_target_sdk_version, @@ -415,10 +393,10 @@ let type_ptr_equal_type type_ptr type_str = | _ -> Logging.out "Couldn't find type....\n"; false -let method_return_type an typ = +let method_return_type an _typ = Logging.out "\n Executing method_return_type..."; - match an with - | Ctl_parser_types.Decl (Clang_ast_t.ObjCMethodDecl (_, _, mdi)) -> + match an, _typ with + | Ctl_parser_types.Decl (Clang_ast_t.ObjCMethodDecl (_, _, mdi)), ALVar.Const typ -> Logging.out "\n with parameter `%s`...." typ; let qual_type = mdi.Clang_ast_t.omdi_result_type in type_ptr_equal_type qual_type.Clang_ast_t.qt_type_ptr typ diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index 9eaf6fbb6..c8c6fbacf 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -13,23 +13,15 @@ type t = ALVar.formula_id * ALVar.alexp list (* (name, [param1,...,paramK]) *) val captured_variables_cxx_ref : Ctl_parser_types.ast_node -> Clang_ast_t.named_decl_info list -val call_method_strict : Ctl_parser_types.ast_node -> string -> bool +val call_method : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val call_method : Ctl_parser_types.ast_node -> string -> bool +val call_class_method : Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool -val call_class_method : Ctl_parser_types.ast_node -> string -> string -> bool +val call_instance_method : Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool -val call_class_method_strict : Ctl_parser_types.ast_node -> string -> string -> bool +val is_objc_interface_named : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val call_instance_method : Ctl_parser_types.ast_node -> string -> string -> bool - -val call_instance_method_strict : Ctl_parser_types.ast_node -> string -> string -> bool - -val is_objc_interface_named_strict : Ctl_parser_types.ast_node -> string -> bool - -val is_objc_interface_named : Ctl_parser_types.ast_node -> string -> bool - -val property_name_contains_word : string -> Ctl_parser_types.ast_node -> bool +val property_named : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val is_objc_extension : CLintersContext.context -> bool @@ -37,7 +29,7 @@ val is_syntactically_global_var : Ctl_parser_types.ast_node -> bool val is_const_expr_var : Ctl_parser_types.ast_node -> bool -val call_function_named : string list -> Ctl_parser_types.ast_node -> bool +val call_function_named : Ctl_parser_types.ast_node -> ALVar.alexp list -> bool val is_strong_property : Ctl_parser_types.ast_node -> bool @@ -49,7 +41,8 @@ val context_in_synchronized_block : CLintersContext.context -> bool val is_ivar_atomic : Ctl_parser_types.ast_node -> bool -val is_method_property_accessor_of_ivar : Ctl_parser_types.ast_node -> CLintersContext.context -> bool +val is_method_property_accessor_of_ivar : + Ctl_parser_types.ast_node -> CLintersContext.context -> bool val is_objc_constructor : CLintersContext.context -> bool @@ -57,28 +50,24 @@ val is_objc_dealloc : CLintersContext.context -> bool val captures_cxx_references : Ctl_parser_types.ast_node -> bool -val is_binop_with_kind : string -> Ctl_parser_types.ast_node -> bool - -val is_unop_with_kind : string -> Ctl_parser_types.ast_node -> bool - -val isa : string -> Ctl_parser_types.ast_node -> bool +val is_binop_with_kind : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val is_node : string -> Ctl_parser_types.ast_node -> bool +val is_unop_with_kind : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val declaration_has_name : Ctl_parser_types.ast_node -> string -> bool +val isa : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val declaration_has_name_strict : Ctl_parser_types.ast_node -> string -> bool +val is_node : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val is_class : Ctl_parser_types.ast_node -> string -> bool +val declaration_has_name : Ctl_parser_types.ast_node -> ALVar.alexp -> bool -val is_class_strict : Ctl_parser_types.ast_node -> string -> bool +val is_class : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val pp_predicate : Format.formatter -> t -> unit -val decl_unavailable_in_supported_ios_sdk : CLintersContext.context -> Ctl_parser_types.ast_node - -> bool +val decl_unavailable_in_supported_ios_sdk : + CLintersContext.context -> Ctl_parser_types.ast_node -> bool -val method_return_type : Ctl_parser_types.ast_node -> string -> bool +val method_return_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val get_available_attr_ios_sdk : Ctl_parser_types.ast_node -> string option diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 26454faeb..69d1a40e0 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -594,30 +594,22 @@ let next_state_via_transition an trans = (* evaluate an atomic formula (i.e. a predicate) on a ast node an and a linter context lcxt. That is: an, lcxt |= pred_name(params) *) -let rec eval_Atomic _pred_name _args an lcxt = +let rec eval_Atomic _pred_name args an lcxt = let pred_name = ALVar.formula_id_to_string _pred_name in - let args = List.map ~f:ALVar.alexp_to_string _args in match pred_name, args, an with | "call_method", [m], an -> CPredicates.call_method an m - | "call_method_strict", [m], an -> CPredicates.call_method_strict an m | "call_class_method", [c; m], an -> CPredicates.call_class_method an c m - | "call_class_method_strict", [c; m], an -> - CPredicates.call_class_method_strict an c m | "call_instance_method", [c; m], an -> CPredicates.call_instance_method an c m - | "call_instance_method_strict", [c; m], an -> - CPredicates.call_instance_method_strict an c m | "is_objc_interface_named", [name], an -> CPredicates.is_objc_interface_named an name - | "is_objc_interface_named_strict", [name], an -> - CPredicates.is_objc_interface_named_strict an name - | "property_name_contains_word", [word], an -> - CPredicates.property_name_contains_word word an + | "property_named", [word], an -> + CPredicates.property_named an word | "is_objc_extension", [], _ -> CPredicates.is_objc_extension lcxt | "is_global_var", [], an -> CPredicates.is_syntactically_global_var an | "is_const_var", [], an -> CPredicates.is_const_expr_var an - | "call_function_named", args, an -> CPredicates.call_function_named args an + | "call_function_named", args, an -> CPredicates.call_function_named an args | "is_strong_property", [], an -> CPredicates.is_strong_property an | "is_assign_property", [], an -> CPredicates.is_assign_property an | "is_property_pointer_type", [], an -> CPredicates.is_property_pointer_type an @@ -629,18 +621,15 @@ let rec eval_Atomic _pred_name _args an lcxt = | "is_objc_constructor", [], _ -> CPredicates.is_objc_constructor lcxt | "is_objc_dealloc", [], _ -> CPredicates.is_objc_dealloc lcxt | "captures_cxx_references", [], _ -> CPredicates.captures_cxx_references an - | "is_binop_with_kind", [str_kind], an -> - CPredicates.is_binop_with_kind str_kind an - | "is_unop_with_kind", [str_kind], an -> - CPredicates.is_unop_with_kind str_kind an - | "is_node", [nodename], an -> CPredicates.is_node nodename an - | "isa", [classname], an -> CPredicates.isa classname an + | "is_binop_with_kind", [kind], an -> + CPredicates.is_binop_with_kind an kind + | "is_unop_with_kind", [kind], an -> + CPredicates.is_unop_with_kind an kind + | "is_node", [nodename], an -> CPredicates.is_node an nodename + | "isa", [classname], an -> CPredicates.isa an classname | "declaration_has_name", [decl_name], an -> CPredicates.declaration_has_name an decl_name - | "declaration_has_name_strict", [decl_name], an -> - CPredicates.declaration_has_name_strict an decl_name | "is_class", [cname], an -> CPredicates.is_class an cname - | "is_class_strict", [cname], an -> CPredicates.is_class_strict an cname | "decl_unavailable_in_supported_ios_sdk", [], an -> CPredicates.decl_unavailable_in_supported_ios_sdk lcxt an | "within_responds_to_selector_block", [], an -> diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al b/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al index af85afb62..0d3d950eb 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/linters_example.al @@ -8,7 +8,7 @@ GLOBAL-MACROS { }; -// Check that class A is not subclassed. +//Check that class A is not subclassed. DEFINE-CHECKER SUBCLASSING_TEST_EXAMPLE = { SET report_when = @@ -22,7 +22,7 @@ DEFINE-CHECKER MACRO_TEST1 = { LET call_two_methods(x,y) = call_method(x) OR call_method(y); - SET report_when = call_two_methods("foo", "bar"); + SET report_when = call_two_methods("foo:", "bar"); SET message = "Error message here"; @@ -31,9 +31,9 @@ DEFINE-CHECKER MACRO_TEST1 = { // Test reverse parameter of macro DEFINE-CHECKER MACRO_TEST2 = { - LET my_macro_to_call_method_of_class(x,y) = call_instance_method(y,x); + LET my_macro_to_call_method_of_class(x,y) = call_instance_method(y,x); - SET report_when = my_macro_to_call_method_of_class("foo", "A"); + SET report_when = my_macro_to_call_method_of_class("foo:", "A"); SET message = "Error message here"; @@ -46,7 +46,7 @@ DEFINE-CHECKER MACRO_TEST3 = { LET call_my_macro(t,v) = my_macro_to_call_method_of_class(t,v); - SET report_when = call_my_macro("foo", "A"); + SET report_when = call_my_macro("foo:", "A"); SET message = "Error message here";