def create_termination_check(self, ignore_measures: bool) -> sil.BoolExpression: """Create a check if callee is going to terminate. This method is essentially a ``tcond`` macro as defined in ``MustTerminate`` documentation. """ disjuncts = [] for instance in self._get_must_terminate_instances(): guard = instance.create_guard_expression() if ignore_measures: disjuncts.append(guard) else: measure_check = self._check_must_terminate_measure_decrease( instance.obligation_instance.get_measure()) disjuncts.append(sil.BigAnd([guard, measure_check])) return sil.BigOr(disjuncts)
def _add_leak_check(self) -> None: """Add leak checks to invariant.""" reference_name = self._ctx.actual_function.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) loop_check_before = sil.BoolVar( self._loop_obligation_info.loop_check_before_var) termination_flag = sil.BoolVar( self._loop_obligation_info.termination_flag_var) if not obligation_config.disable_loop_context_leak_check: must_terminate = self._obligation_manager.must_terminate_obligation predicate = must_terminate.create_predicate_access( self._obligation_info.current_thread_var) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() loop_cond = self._loop_obligation_info.construct_loop_condition() before_loop_leak_check = sil.InhaleExhale( sil.TrueLit(), sil.Implies( loop_check_before, sil.BigOr([ termination_flag, sil.Not(loop_cond), sil.BigAnd([termination_leak_check, leak_check]) ]))) info = self._to_info('Leak check for context.') position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_CONTEXT_LEAK_CHECK_FAIL) self._obligation_loop.append_invariants([ before_loop_leak_check.translate(self._translator, self._ctx, position, info) ]) if not obligation_config.disable_loop_body_leak_check: body_leak_check = sil.InhaleExhale( sil.TrueLit(), sil.Implies(sil.Not(loop_check_before), leak_check)) info = self._to_info('Leak check for loop body.') position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_BODY_LEAK_CHECK_FAIL) self._obligation_loop.append_invariants([ body_leak_check.translate(self._translator, self._ctx, position, info) ])
def _check_loop_preserves_termination(self) -> None: """Check that loop keeps the promise to terminate.""" if obligation_config.disable_termination_check: return check = sil.Implies( sil.BoolVar(self._loop_obligation_info.termination_flag_var), sil.BigOr([ sil.Not(self._loop_obligation_info.construct_loop_condition()), self._loop_obligation_info.create_termination_check(False) ])) assertion = sil.Assert(check) position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_TERMINATION_PROMISE_FAIL) comment = 'Check if loop continues to terminate.' if isinstance(self._viper, ViperASTExtended): info = self._viper.SIFInfo([comment], continue_unaware=True) else: info = self._to_info(comment) statement = assertion.translate(self._translator, self._ctx, position, info) self._obligation_loop.append_body(statement)
def _add_caller_leak_check(self) -> None: """Add a leak check. Check that if callee is not terminating, caller has no obligations. """ if obligation_config.disable_call_context_leak_check: return # MustTerminate leak check. must_terminate = self._obligation_manager.must_terminate_obligation cthread = self._obligation_info.current_thread_var predicate = must_terminate.create_predicate_access(cthread) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() # Other obligations leak check. reference_name = self._python_method.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) if self._python_method.interface: if must_terminate.is_interface_method_terminating( self._python_method.interface_dict): exhale = self._obligation_info.caller_measure_map.check( sil.RefVar(self._obligation_info.current_thread_var), sil.RawIntExpression(1)) else: exhale = sil.BigAnd([termination_leak_check, leak_check]) else: # Termination condition. tcond = self._obligation_info.create_termination_check(False) # Combination. exhale = sil.BigOr( [tcond, sil.BigAnd([termination_leak_check, leak_check])]) check = sil.InhaleExhale(sil.TrueLit(), exhale) # Translate to Silver. node = self.get_function_node() position = self._translator.to_position( node, self._ctx, rules=rules.OBLIGATION_CALL_LEAK_CHECK_FAIL) info = self._translator.to_info(["Caller side leak check"], self._ctx) precondition = check.translate(self._translator, self._ctx, position, info) self._obligation_method.append_preconditions([precondition])