Skip to content

Commit cba47b2

Browse files
committed
CMD: add command-line option to control status of system includes
1 parent f955d84 commit cba47b2

File tree

9 files changed

+112
-31
lines changed

9 files changed

+112
-31
lines changed

chc/app/CApplication.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,14 @@ def __init__(
9393
targetpath: str,
9494
contractpath: str,
9595
singlefile: bool = False,
96+
keep_system_includes: bool = False,
9697
excludefiles: List[str] = []) -> None:
9798
self._projectpath = projectpath
9899
self._projectname = projectname
99100
self._targetpath = targetpath
100101
self._contractpath = contractpath
101102
self._singlefile = singlefile
103+
self._keep_system_includes = keep_system_includes
102104
self._excludefiles = excludefiles
103105
self._indexmanager = IndexManager(singlefile)
104106
self._globalcontract: Optional[CGlobalContract] = None
@@ -138,6 +140,19 @@ def globalcontract(self) -> CGlobalContract:
138140
def is_singlefile(self) -> bool:
139141
return self._singlefile
140142

143+
@property
144+
def keep_system_includes(self) -> bool:
145+
"""Returns true if functions from the system path ('/') must be included
146+
147+
This property is false by default and must be enabled via a command-line
148+
option.
149+
150+
It is intended to, by default, filter out functions defined in header
151+
files, that would otherwise be included in every source file.
152+
"""
153+
154+
return self._keep_system_includes
155+
141156
@property
142157
def excludefiles(self) -> List[str]:
143158
return self._excludefiles

chc/app/CFile.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ def name(self) -> str:
154154
def capp(self) -> "CApplication":
155155
return self._capp
156156

157+
@property
158+
def keep_system_includes(self) -> bool:
159+
return self.capp.keep_system_includes
160+
157161
@property
158162
def targetpath(self) -> str:
159163
return self.capp.targetpath

chc/app/CFileGlobals.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ def __init__(self, cfile: "CFile", xnode: ET.Element) -> None:
179179
def cfile(self) -> "CFile":
180180
return self._cfile
181181

182+
@property
183+
def keep_system_includes(self) -> bool:
184+
return self.cfile.keep_system_includes
185+
182186
@property
183187
def declarations(self) -> "CFileDeclarations":
184188
return self.cfile.declarations
@@ -284,6 +288,16 @@ def gfunctions(self) -> Dict[int, CGFunction]:
284288
xiloc = xf.get("iloc")
285289
if xivinfo is not None and xiloc is not None:
286290
vinfo = self.declarations.get_varinfo(int(xivinfo))
291+
if (
292+
not self.keep_system_includes
293+
and vinfo.vdecl is not None
294+
and vinfo.vdecl.file.startswith("/")):
295+
chklogger.logger.info(
296+
"%s: Skip system function %s defined in %s",
297+
self.cfile.cfilename,
298+
vinfo.vname,
299+
vinfo.vdecl.file)
300+
continue
287301
loc = self.declarations.get_location(int(xiloc))
288302
gfun = CGFunction(loc, vinfo)
289303
self._gfunctions[vinfo.vid] = gfun

chc/app/CHVersion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
chcversion: str = "0.2.0-2024-11-04"
1+
chcversion: str = "0.2.0-2025-10-24"

chc/cmdline/AnalysisManager.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def __init__(
5454
wordsize: int = 0,
5555
unreachability: bool = False,
5656
thirdpartysummaries: List[str] = [],
57-
nofilter: bool = True,
57+
keep_system_includes: bool = False,
5858
verbose: bool = False,
5959
) -> None:
6060
"""Initialize the analyzer location and target file location.
@@ -72,13 +72,8 @@ def __init__(
7272
"""
7373

7474
self._capp = capp
75-
# self.contractpath = capp.contractpath
7675
self._config = Config()
77-
# self.chsummaries = self.config.summaries
78-
# self.path = self.capp.path
79-
# self.canalyzer = self.config.canalyzer
80-
# self.gui = self.config.chc_gui
81-
self.nofilter = nofilter
76+
self._keep_system_includes = keep_system_includes
8277
self.wordsize = wordsize
8378
self.thirdpartysummaries = thirdpartysummaries
8479
self.unreachability = unreachability
@@ -88,6 +83,10 @@ def __init__(
8883
def capp(self) -> "CApplication":
8984
return self._capp
9085

86+
@property
87+
def keep_system_includes(self) -> bool:
88+
return self._keep_system_includes
89+
9190
@property
9291
def contractpath(self) -> Optional[str]:
9392
return self.capp.contractpath
@@ -189,8 +188,8 @@ def _create_file_primary_proofobligations_cmd_partial(self) -> List[str]:
189188
cmd.extend(["-contractpath", self.contractpath])
190189
cmd.extend(["-projectname", self.capp.projectname])
191190

192-
if self.nofilter:
193-
cmd.append("-nofilter")
191+
if self.keep_system_includes:
192+
cmd.append("-keep_system_includes")
194193
if self.wordsize > 0:
195194
cmd.extend(["-wordsize", str(self.wordsize)])
196195
cmd.append(self.targetpath)
@@ -283,8 +282,8 @@ def _generate_and_check_file_cmd_partial(
283282
if not (self.contractpath is None):
284283
cmd.extend(["-contractpath", self.contractpath])
285284
cmd.extend(["-projectname", self.capp.projectname])
286-
if self.nofilter:
287-
cmd.append("-nofilter")
285+
if self.keep_system_includes:
286+
cmd.append("-keep_system_includes")
288287
if self.wordsize > 0:
289288
cmd.extend(["-wordsize", str(self.wordsize)])
290289
if self.unreachability:

chc/cmdline/ParseManager.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def __init__(
7272
projectpath: str,
7373
projectname: str,
7474
targetpath: str,
75-
filter: bool = False,
75+
keep_system_includes: bool = False,
7676
posix: bool = False,
7777
verbose: bool = True,
7878
keepUnused: bool = False,
@@ -96,7 +96,7 @@ def __init__(
9696
self._targetpath, self._projectname)
9797
self._analysisresultspath = UF.get_analysisresults_path(
9898
self._targetpath, self._projectname)
99-
self._filter = filter
99+
self._keep_system_includes = keep_system_includes
100100
self._posix = posix
101101
self._keepUnused = keepUnused
102102
self._verbose = verbose
@@ -160,8 +160,8 @@ def tgtplatform(self) -> str:
160160
return self._tgtplatform
161161

162162
@property
163-
def filter(self) -> bool:
164-
return self._filter
163+
def keep_system_includes(self) -> bool:
164+
return self._keep_system_includes
165165

166166
@property
167167
def posix(self) -> bool:
@@ -439,8 +439,8 @@ def parse_with_ccommands(
439439
"-targetdirectory",
440440
self.analysisresultspath
441441
]
442-
if not self.filter:
443-
command.append("-nofilter")
442+
if self.keep_system_includes:
443+
command.append("-keep_system_includes")
444444
if self.keepUnused:
445445
command.append("-keepUnused")
446446
command.append(ifilename)
@@ -533,8 +533,8 @@ def parse_ifile(self, ifilename: str) -> int:
533533
"-targetdirectory",
534534
self.analysisresultspath,
535535
]
536-
if not self.filter:
537-
cmd.append("-nofilter")
536+
if not self.keep_system_includes:
537+
cmd.append("-keep_system_includes")
538538
if self.keepUnused:
539539
cmd.append("-keepUnused")
540540
cmd.append(ifilename)

chc/cmdline/c_file/cfileutil.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def cfile_parse_file(args: argparse.Namespace) -> NoReturn:
117117
# arguments
118118
pcfilename: str = os.path.abspath(args.filename)
119119
opttgtpath: Optional[str] = args.tgtpath
120+
keep_system_includes: bool = args.keep_system_includes
120121
loglevel: str = args.loglevel
121122
logfilename: Optional[str] = args.logfilename
122123
logfilemode: str = args.logfilemode
@@ -154,7 +155,8 @@ def cfile_parse_file(args: argparse.Namespace) -> NoReturn:
154155

155156
chklogger.logger.info("Target path: %s", targetpath)
156157

157-
parsemanager = ParseManager(projectpath, projectname, targetpath)
158+
parsemanager = ParseManager(
159+
projectpath, projectname, targetpath, keep_system_includes=keep_system_includes)
158160
parsemanager.remove_semantics()
159161
parsemanager.initialize_paths()
160162

@@ -418,6 +420,7 @@ def cfile_analyze_file(args: argparse.Namespace) -> NoReturn:
418420
xcfilename: str = args.filename
419421
opttgtpath: Optional[str] = args.tgtpath
420422
wordsize: int = args.wordsize
423+
keep_system_includes: bool = args.keep_system_includes
421424
verbose: bool = args.verbose
422425
loglevel: str = args.loglevel
423426
logfilename: Optional[str] = args.logfilename
@@ -468,12 +471,21 @@ def cfile_analyze_file(args: argparse.Namespace) -> NoReturn:
468471
contractpath = os.path.join(targetpath, "chc_contracts")
469472

470473
capp = CApplication(
471-
projectpath, projectname, targetpath, contractpath, singlefile=True)
474+
projectpath,
475+
projectname,
476+
targetpath,
477+
contractpath,
478+
singlefile=True,
479+
keep_system_includes=keep_system_includes)
472480

473481
capp.initialize_single_file(cfilename)
474482
cfile = capp.get_cfile()
475483

476-
am = AnalysisManager(capp, verbose=verbose, wordsize=wordsize)
484+
am = AnalysisManager(
485+
capp,
486+
verbose=verbose,
487+
wordsize=wordsize,
488+
keep_system_includes=keep_system_includes)
477489

478490
am.create_file_primary_proofobligations(cfilename)
479491
am.reset_tables(cfile)
@@ -578,6 +590,7 @@ def cfile_run_file(args: argparse.Namespace) -> NoReturn:
578590
# arguments
579591
pcfilename: str = os.path.abspath(args.filename)
580592
opttgtpath: Optional[str] = args.tgtpath
593+
keep_system_includes: bool = args.keep_system_includes
581594
cshowcode: bool = args.showcode
582595
copen: bool = args.open
583596
cshowinvariants: bool = args.showinvariants
@@ -622,7 +635,8 @@ def cfile_run_file(args: argparse.Namespace) -> NoReturn:
622635

623636
chklogger.logger.info("Target path: %s", targetpath)
624637

625-
parsemanager = ParseManager(projectpath, projectname, targetpath)
638+
parsemanager = ParseManager(
639+
projectpath, projectname, targetpath, keep_system_includes=keep_system_includes)
626640
parsemanager.remove_semantics()
627641
parsemanager.initialize_paths()
628642

@@ -672,7 +686,12 @@ def cfile_run_file(args: argparse.Namespace) -> NoReturn:
672686
contractpath = os.path.join(targetpath, "chc_contracts")
673687

674688
capp = CApplication(
675-
projectpath, projectname, targetpath, contractpath, singlefile=True)
689+
projectpath,
690+
projectname,
691+
targetpath,
692+
contractpath,
693+
singlefile=True,
694+
keep_system_includes=keep_system_includes)
676695

677696
capp.initialize_single_file(cfilename)
678697
cfile = capp.get_cfile()
@@ -695,7 +714,12 @@ def cfile_run_file(args: argparse.Namespace) -> NoReturn:
695714
chklogger.logger.info("cfile analyze completed")
696715

697716
capp = CApplication(
698-
projectpath, projectname, targetpath, contractpath, singlefile=True)
717+
projectpath,
718+
projectname,
719+
targetpath,
720+
contractpath,
721+
singlefile=True,
722+
keep_system_includes=keep_system_includes)
699723
capp.initialize_single_file(cfilename)
700724
cfile = capp.get_cfile()
701725

chc/cmdline/c_project/cprojectutil.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868

6969
def print_error(m: str) -> None:
7070
sys.stderr.write(("*" * 80) + "\n")
71-
sys.stderr.write(m + "\n")
71+
sys.stderr.write("F:" + m + "\n")
7272
sys.stderr.write(("*" * 80) + "\n")
7373

7474

@@ -110,6 +110,7 @@ def cproject_parse_project(args: argparse.Namespace) -> NoReturn:
110110
projectpath: str = args.path
111111
projectname: str = args.projectname
112112
opttgtpath: Optional[str] = args.tgtpath
113+
keep_system_includes: bool = args.keep_system_includes
113114
loglevel: str = args.loglevel
114115
logfilename: Optional[str] = args.logfilename
115116
logfilemode: str = args.logfilemode
@@ -156,7 +157,8 @@ def cproject_parse_project(args: argparse.Namespace) -> NoReturn:
156157
print_error("The compile_commands.json file was found empty")
157158
exit(1)
158159

159-
parsemanager = ParseManager(projectpath, projectname, targetpath)
160+
parsemanager = ParseManager(
161+
projectpath, projectname, targetpath, keep_system_includes=keep_system_includes)
160162
parsemanager.remove_semantics()
161163
parsemanager.initialize_paths()
162164
parsemanager.parse_with_ccommands(compilecommands, copyfiles=True)
@@ -423,6 +425,7 @@ def cproject_analyze_project(args: argparse.Namespace) -> NoReturn:
423425
# arguments
424426
tgtpath: str = args.tgtpath
425427
projectname: str = args.projectname
428+
keep_system_includes: bool = args.keep_system_includes
426429
maxprocesses: int = args.maxprocesses
427430
loglevel: str = args.loglevel
428431
logfilename: Optional[str] = args.logfilename
@@ -458,6 +461,7 @@ def cproject_analyze_project(args: argparse.Namespace) -> NoReturn:
458461
projectname,
459462
targetpath,
460463
contractpath,
464+
keep_system_includes=keep_system_includes,
461465
excludefiles=excludefiles)
462466

463467
def save_xrefs(f: "CFile") -> None:
@@ -475,9 +479,10 @@ def save_xrefs(f: "CFile") -> None:
475479
projectname,
476480
targetpath,
477481
contractpath,
482+
keep_system_includes=keep_system_includes,
478483
excludefiles=excludefiles)
479484

480-
am = AnalysisManager(capp, verbose=True)
485+
am = AnalysisManager(capp, verbose=True, keep_system_includes=keep_system_includes)
481486

482487
with timing("analysis"):
483488

@@ -490,13 +495,13 @@ def save_xrefs(f: "CFile") -> None:
490495
exit(1)
491496

492497
for i in range(1):
493-
am.generate_and_check_app("llrvisp", processes=maxprocesses)
498+
am.generate_and_check_app("visp", processes=maxprocesses)
494499
capp.reinitialize_tables()
495500
capp.update_spos()
496501

497502
for i in range(5):
498503
capp.update_spos()
499-
am.generate_and_check_app("llrvisp", processes=maxprocesses)
504+
am.generate_and_check_app("visp", processes=maxprocesses)
500505
capp.reinitialize_tables()
501506

502507
timestamp = os.stat(UF.get_cchpath(targetpath, projectname)).st_ctime

0 commit comments

Comments
 (0)