@@ -367,6 +367,47 @@ bool ungrounded_parameter_checker::visit_identifier(identifier* node) {
367367 return true ;
368368}
369369
370+ bool ungrounded_parameter_checker::check_directly_call_identifier (expr* node) {
371+ if (node->get_ast_class () != ast_class::ac_call_root) {
372+ return false ;
373+ }
374+
375+ auto real = static_cast <call_root*>(node);
376+ if (real->get_call_head ()->has_func_call () ||
377+ real->get_call_head ()->is_initializer ()) {
378+ return false ;
379+ }
380+ if (real->get_call_head ()->get_first_expression ()->get_ast_class ()
381+ != ast_class::ac_identifier) {
382+ return false ;
383+ }
384+ if (!real->get_call_chain ().empty ()) {
385+ return false ;
386+ }
387+
388+ return true ;
389+ }
390+
391+ bool ungrounded_parameter_checker::check_non_binding_binary_operator (binary_operator* node) {
392+ // binary expressions like:
393+ // a - 1, a + 1, a * 1, a / 1
394+ // are used as condition,
395+ // variables directly called in the expression will not be marked as grounded
396+
397+ // both lhs and rhs are not directly called identifier,
398+ // this is definitely not a binding binary operator,
399+ // and we do not need to ignore checkings on both sides
400+ if (!check_directly_call_identifier (node->get_left ()) &&
401+ !check_directly_call_identifier (node->get_right ())) {
402+ return false ;
403+ }
404+
405+ return node->get_operator_type () == binary_operator::type::add ||
406+ node->get_operator_type () == binary_operator::type::sub ||
407+ node->get_operator_type () == binary_operator::type::mult ||
408+ node->get_operator_type () == binary_operator::type::div;
409+ }
410+
370411bool ungrounded_parameter_checker::visit_call_expr (call_expr* node) {
371412 // do not visit field name and generic type here
372413 // because they include identifier nodes, which may
@@ -398,12 +439,34 @@ bool ungrounded_parameter_checker::visit_unary_operator(unary_operator* node) {
398439bool ungrounded_parameter_checker::visit_binary_operator (binary_operator* node) {
399440 // not in logical or expression, just visit and exit
400441 if (!logical_or_variable_used.size ()) {
442+ // e.g. `a + 1`, we do not check `a`
443+ // e.g. `a + f(a)`, we do not check `a` but we check `f(a)`
444+ if (check_non_binding_binary_operator (node)) {
445+ if (!check_directly_call_identifier (node->get_left ())) {
446+ node->get_left ()->accept (this );
447+ }
448+ if (!check_directly_call_identifier (node->get_right ())) {
449+ node->get_right ()->accept (this );
450+ }
451+ return true ;
452+ }
401453 node->get_left ()->accept (this );
402454 node->get_right ()->accept (this );
403455 return true ;
404456 }
405457
406- if (node->get_operator_type ()!=binary_operator::type::logical_or) {
458+ if (node->get_operator_type () != binary_operator::type::logical_or) {
459+ // e.g. `a + 1`, we do not check `a`
460+ // e.g. `a + f(a)`, we do not check `a` but we check `f(a)`
461+ if (check_non_binding_binary_operator (node)) {
462+ if (!check_directly_call_identifier (node->get_left ())) {
463+ node->get_left ()->accept (this );
464+ }
465+ if (!check_directly_call_identifier (node->get_right ())) {
466+ node->get_right ()->accept (this );
467+ }
468+ return true ;
469+ }
407470 node->get_left ()->accept (this );
408471 node->get_right ()->accept (this );
409472 return true ;
0 commit comments