|
56 | 56 | import subprocess |
57 | 57 | import sys |
58 | 58 |
|
| 59 | + |
59 | 60 | from typing import ( |
60 | 61 | Any, Callable, cast, Dict, List, NoReturn, Optional, TYPE_CHECKING) |
61 | 62 |
|
|
73 | 74 | from chc.util.loggingutil import chklogger, LogLevel |
74 | 75 |
|
75 | 76 | if TYPE_CHECKING: |
| 77 | + from chc.invariants.CInvariantFact import CInvariantNRVFact |
76 | 78 | from chc.app.CAttributes import CAttributes |
77 | 79 | from chc.app.CTyp import ( |
78 | 80 | CTypComp, CTypFloat, CTypFun, CTypInt, CTypPtr) |
@@ -813,6 +815,62 @@ def header(s: str) -> str: |
813 | 815 | exit(0) |
814 | 816 |
|
815 | 817 |
|
| 818 | +def cfile_query_invariants(args: argparse.Namespace) -> NoReturn: |
| 819 | + |
| 820 | + # arguments |
| 821 | + xcfilename: str = args.filename |
| 822 | + opttgtpath: Optional[str] = args.tgtpath |
| 823 | + xfunction: str = args.function |
| 824 | + xline: int = args.line |
| 825 | + |
| 826 | + projectpath = os.path.dirname(os.path.abspath(xcfilename)) |
| 827 | + targetpath = projectpath if opttgtpath is None else opttgtpath |
| 828 | + targetpath = os.path.abspath(targetpath) |
| 829 | + cfilename_c = os.path.basename(xcfilename) |
| 830 | + cfilename = cfilename_c[:-2] |
| 831 | + projectname = cfilename |
| 832 | + |
| 833 | + cchpath = UF.get_cchpath(targetpath, projectname) |
| 834 | + contractpath = os.path.join(targetpath, "chc_contracts") |
| 835 | + |
| 836 | + if not UF.check_analysis_results_files(targetpath, projectname, None, cfilename): |
| 837 | + print_error("No analysis results found for " + cfilename |
| 838 | + + ". Please run analyzer first.") |
| 839 | + exit(1) |
| 840 | + |
| 841 | + capp = CApplication( |
| 842 | + projectpath, projectname, targetpath, contractpath, singlefile=True) |
| 843 | + capp.initialize_single_file(cfilename) |
| 844 | + cfile = capp.get_cfile() |
| 845 | + |
| 846 | + if not cfile.has_function_by_name(xfunction): |
| 847 | + print_error("No function found with name " + xfunction) |
| 848 | + exit(1) |
| 849 | + |
| 850 | + cfun = cfile.get_function_by_name(xfunction) |
| 851 | + ppos = cfun.get_ppos() |
| 852 | + contexts = {ppo.context for ppo in ppos if ppo.line == xline} |
| 853 | + |
| 854 | + print("Invariants for function " + xfunction + ", line " + str(xline)) |
| 855 | + if len(contexts) == 0: |
| 856 | + print("\nNo ast positions found with invariants on line " + str(xline) + ".") |
| 857 | + exit(0) |
| 858 | + |
| 859 | + for ctxt in contexts: |
| 860 | + print("\nAST position: " + str(ctxt)) |
| 861 | + print("-" * (len(str(ctxt)) + 14)) |
| 862 | + invs = cfun.invarianttable.get_sorted_invariants(ctxt) |
| 863 | + nrvfacts: List[str] = [] |
| 864 | + for inv in invs: |
| 865 | + if inv.is_nrv_fact: |
| 866 | + inv = cast("CInvariantNRVFact", inv) |
| 867 | + if not inv.variable.is_check_variable: |
| 868 | + nrvfacts.append(str(inv)) |
| 869 | + print("\n".join(nrvfacts)) |
| 870 | + |
| 871 | + exit(0) |
| 872 | + |
| 873 | + |
816 | 874 | def cfile_testlibc_summary(args: argparse.Namespace) -> NoReturn: |
817 | 875 | """Runs one of the programs in tests/libcsummaries |
818 | 876 |
|
|
0 commit comments