Skip to content

Commit 5d9f0f2

Browse files
committed
CMD: add investigate command for projects
1 parent bad32a4 commit 5d9f0f2

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

chc/cmdline/c_project/cprojectutil.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ def cproject_report(args: argparse.Namespace) -> NoReturn:
540540
statsresult = UF.read_project_summary_results(targetpath, projectname)
541541
if statsresult is not None:
542542
print(RP.project_proofobligation_stats_dict_to_string(statsresult))
543-
if canalysis == "undefinedbehavior":
543+
if canalysis == "undefined-behavior":
544544
exit(0)
545545

546546
if not UF.has_analysisresults_path(targetpath, projectname):
@@ -637,6 +637,64 @@ def callsite_str(instr: "CCallInstr") -> str:
637637
exit(0)
638638

639639

640+
def cproject_investigate(args: argparse.Namespace) -> NoReturn:
641+
642+
# arguments
643+
tgtpath: str = args.tgtpath
644+
projectname: str = args.projectname
645+
predicates: Optional[List[str]] = args.predicates
646+
647+
targetpath = os.path.abspath(tgtpath)
648+
projectpath = targetpath
649+
contractpath = os.path.join(targetpath, "chc_contracts")
650+
651+
if not UF.has_analysisresults_path(targetpath, projectname):
652+
print_error(
653+
f"No analysis results found for {projectname} in {targetpath}")
654+
exit(1)
655+
656+
capp = CApplication(
657+
projectpath, projectname, targetpath, contractpath)
658+
659+
def pofilter(po: "CFunctionPO") -> bool:
660+
if predicates is not None:
661+
return po.predicate_name in predicates
662+
else:
663+
return True
664+
665+
def header(s: str) -> str:
666+
return (s + ":\n" + ("=" * 80))
667+
668+
lines: List[str] = []
669+
670+
for cfile in capp.cfiles:
671+
openppos = cfile.get_open_ppos()
672+
violations = cfile.get_ppos_violated()
673+
delegated = cfile.get_ppos_delegated()
674+
675+
if len(openppos) + len(violations) + len(delegated) > 0:
676+
lines.append("=" * 80)
677+
lines.append(cfile.name)
678+
lines.append("=" * 80)
679+
680+
if len(openppos) > 0:
681+
lines.append(header("Open primary proof obligations obligations"))
682+
lines.append(RP.tag_file_function_pos_tostring(openppos, pofilter=pofilter))
683+
684+
if len(violations) > 0:
685+
lines.append(header("Primary proof obligations violated"))
686+
lines.append(RP.tag_file_function_pos_tostring(
687+
violations, pofilter=pofilter))
688+
689+
if len(delegated) > 0:
690+
lines.append(header("Primary proof obligations delegated"))
691+
lines.append(RP.tag_file_function_pos_tostring(delegated, pofilter=pofilter))
692+
693+
print("\n".join(lines))
694+
695+
exit(0)
696+
697+
640698
def cproject_count_stmts(args: argparse.Namespace) -> NoReturn:
641699
"""CLI command to output size statistics for a c project."""
642700

chc/cmdline/chkc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,18 @@ def parse() -> argparse.Namespace:
16211621
help="show location invariants on the code")
16221622
cprojectreportfile.set_defaults(func=P.cproject_report_file)
16231623

1624+
# --- investigate
1625+
cprojectinvestigate = cprojectparsers.add_parser("investigate")
1626+
cprojectinvestigate.add_argument(
1627+
"tgtpath", help="directory that contains the analysis results")
1628+
cprojectinvestigate.add_argument(
1629+
"projectname", help="name of the project")
1630+
cprojectinvestigate.add_argument(
1631+
"--predicates",
1632+
nargs="*",
1633+
help="names of predicates of interest, e.g., not-null (default: all")
1634+
cprojectinvestigate.set_defaults(func=P.cproject_investigate)
1635+
16241636
# --- count-statements
16251637
cprojectcountstmts = cprojectparsers.add_parser("count-statements")
16261638
cprojectcountstmts.add_argument(

0 commit comments

Comments
 (0)