-
Notifications
You must be signed in to change notification settings - Fork 457
Expand file tree
/
Copy pathanalyze.py
More file actions
1523 lines (1312 loc) · 68.3 KB
/
analyze.py
File metadata and controls
1523 lines (1312 loc) · 68.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# -------------------------------------------------------------------------
#
# Part of the CodeChecker project, under the Apache License v2.0 with
# LLVM Exceptions. See LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# -------------------------------------------------------------------------
"""
Execute analysis over an already existing build.json compilation database.
"""
import argparse
import collections
import json
import os
import shutil
import sys
from typing import List
from pathlib import Path
from functools import partial
from tu_collector import tu_collector
from codechecker_analyzer import analyzer, analyzer_context, \
compilation_database
from codechecker_analyzer.analyzers import analyzer_types, clangsa
from codechecker_analyzer.arg import \
OrderedCheckersAction, OrderedConfigAction, existing_abspath, \
analyzer_config, checker_config, AnalyzerConfigArg, CheckerConfigArg
from codechecker_analyzer.buildlog import log_parser
from codechecker_common import arg, logger, cmd_config, review_status_handler
from codechecker_common.compatibility.multiprocessing import cpu_count
from codechecker_common.skiplist_handler import SkipListHandler, \
SkipListHandlers
from codechecker_common.util import load_json
LOG = logger.get_logger('system')
header_file_extensions = (
'.h', '.hh', '.H', '.hp', '.hxx', '.hpp', '.HPP', '.h++', '.tcc')
EPILOG_ENV_VAR = """
CC_ANALYZERS_FROM_PATH Set to `yes` or `1` to enforce taking the analyzers
from the `PATH` instead of the given binaries.
CC_ANALYZER_BIN Set the absolute paths of an analyzer binaries.
Overrides other means of CodeChecker getting hold of
binary.
Format: CC_ANALYZER_BIN='<analyzer1>:/path/to/bin1;
<analyzer2>:/path/to/bin2'
CC_CLANGSA_PLUGIN_DIR If the CC_ANALYZERS_FROM_PATH environment variable
is set you can configure the plugin directory of the
Clang Static Analyzer by using this environment
variable.
"""
EPILOG_ISSUE_HASHES = """
Issue hashes
------------------------------------------------
- By default the issue hash calculation method for 'Clang Static Analyzer' is
context sensitive. It means the hash will be generated based on the following
information:
* signature of the enclosing function declaration, type declaration or
namespace.
* content of the line where the bug is.
* unique name of the checker.
* position (column) within the line.
- By default the issue hash calculation method for 'Clang Tidy' is context
insensitive. It means the hash will be generated based on the following
information:
* 'file name' from the main diag section.
* 'checker name'.
* 'checker message'.
* 'line content' from the source file if can be read up.
* 'column numbers' from the main diag section.
* 'range column numbers' only from the control diag sections if column number
in the range is not the same as the previous control diag section number in
the bug path. If there are no control sections event section column numbers
are used.
- context-free: there was a bug and for Clang Tidy the default hash was
generated and not the context free hash (kept for backward compatibility). Use
'context-free-v2' instead of this.
- context-free-v2:
* 'file name' from the main diag section.
* 'checker message'.
* 'line content' from the source file if can be read up. All the whitespaces
from the source content are removed.
* 'column numbers' from the main diag sections location.
- diagnostic-message:
* Same as 'context-free-v2' (file name, checker message etc.)
* 'bug step messages' from all events.
Be careful with this hash because it can change easily for example on
variable / function renames.
OUR RECOMMENDATION: we recommend you to use 'context-free-v2' hash because the
hash will not be changed so easily for example on code indentation or when a
checker is renamed.
For more information see:
https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/report_identification.md
"""
EPILOG_EXIT_STATUS = """
Exit status
------------------------------------------------
0 - Successful analysis
1 - CodeChecker error
3 - Analysis of at least one translation unit failed
128+signum - Terminating on a fatal signal whose number is signum
"""
def get_argparser_ctor_args():
"""
This method returns a dict containing the kwargs for constructing an
argparse.ArgumentParser (either directly or as a subparser).
"""
return {
'prog': 'CodeChecker analyze',
'formatter_class': arg.RawDescriptionDefaultHelpFormatter,
# Description is shown when the command's help is queried directly
'description': """
Use the previously created JSON Compilation Database to perform an analysis on
the project, outputting analysis results in a machine-readable format.""",
# Epilogue is shown after the arguments when the help is queried
# directly.
'epilog': f"""
Environment variables
------------------------------------------------
{EPILOG_ENV_VAR}
{EPILOG_ISSUE_HASHES}
{EPILOG_EXIT_STATUS}
Compilation databases can be created by instrumenting your project's build via
'CodeChecker log'. To transform the results of the analysis to a human-friendly
format, please see the commands 'CodeChecker parse' or 'CodeChecker store'.
""",
# Help is shown when the "parent" CodeChecker command lists the
# individual subcommands.
'help': "Execute the supported code analyzers for the files "
"recorded in a JSON Compilation Database."
}
def add_arguments_to_parser(parser):
"""
Add the subcommand's arguments to the given argparse.ArgumentParser.
"""
parser.add_argument('input',
type=existing_abspath,
help="The input of the analysis can be either a "
"compilation database JSON file, a path to a "
"source file or a path to a directory containing "
"source files.")
parser.add_argument('-j', '--jobs',
type=int,
dest="jobs",
required=False,
default=cpu_count(),
help="Number of threads to use in analysis. More "
"threads mean faster analysis at the cost of "
"using more memory.")
skip_mode = parser.add_argument_group("file filter arguments")
skip_mode.add_argument('-i', '--ignore', '--skip',
dest="skipfile",
required=False,
default=argparse.SUPPRESS,
help="Path to the Skipfile dictating which project "
"files should be omitted from analysis. "
"Please consult the User guide on how a "
"Skipfile should be laid out.")
skip_mode.add_argument('--drop-reports-from-skipped-files',
dest="drop_skipped_reports",
required=False,
action='store_true',
default=False,
help="Filter our reports from files that were "
"skipped from the analysis.")
skip_mode.add_argument('--file',
nargs='+',
dest="files",
metavar='FILE',
required=False,
default=argparse.SUPPRESS,
help="Analyze only the given file(s) not the whole "
"compilation database. Absolute directory "
"paths should start with '/', relative "
"directory paths should start with '*' and "
"it can contain path glob pattern. "
"Example: '/path/to/main.cpp', 'lib/*.cpp', "
"*/test*'.")
parser.add_argument('--review-status-config',
dest="review_status_config",
required=False,
type=existing_abspath,
default=argparse.SUPPRESS,
help="Path of review_status.yaml config file which "
"contains review status settings assigned to "
"specific directories, checkers, bug hashes.")
parser.add_argument('-o', '--output',
dest="output_path",
required=True,
default=argparse.SUPPRESS,
help="Store the analysis output in the given folder.")
parser.add_argument('--compiler-info-file',
dest="compiler_info_file",
required=False,
default=argparse.SUPPRESS,
help="Read the compiler includes and target from the "
"specified file rather than invoke the compiler "
"executable.")
parser.add_argument('--dump-compiler-info-file',
dest="dump_compiler_info_file",
required=False,
action='store_true',
default=False,
help="Dump implicit gcc compiler info to a json file "
"that can be used for fine-tuning analysis later."
"These are information like the implicit include "
"paths of standard headers, the default language "
"version and the default target architecture.")
parser.add_argument('--keep-gcc-include-fixed',
dest="keep_gcc_include_fixed",
required=False,
action='store_true',
default=False,
help="There are some implicit include paths which are "
"only used by GCC (include-fixed). This flag "
"determines whether these should be kept among "
"the implicit include paths.")
parser.add_argument('--keep-gcc-intrin',
dest="keep_gcc_intrin",
required=False,
action='store_true',
default=False,
help="There are some implicit include paths which "
"contain GCC-specific header files (those "
"which end with intrin.h). This flag determines "
"whether these should be kept among the implicit "
"include paths. Use this flag if Clang analysis "
"fails with error message related to __builtin "
"symbols.")
parser.add_argument('--add-gcc-include-dirs-with-isystem',
dest="add_gcc_include_dirs_with_isystem",
required=False,
action='store_true',
default=False,
help="Implicit include directories are appended to "
"the analyzer command with -idirafter. If "
"-isystem is needed instead, as it was used "
"before CodeChecker 6.24.1, this flag can be "
"used.")
parser.add_argument('-t', '--type', '--output-format',
dest="output_format",
required=False,
choices=['plist'],
default='plist',
help="Specify the format the analysis results should "
"use.")
parser.add_argument('--makefile',
dest="makefile",
required=False,
action='store_true',
default=False,
help="Generate a Makefile in the given output "
"directory from the analyzer commands and do not "
"execute the analysis. The analysis can be "
"executed by calling the make command like "
"'make -f output_dir/Makefile'. You can ignore "
"errors with the -i/--ignore-errors options: "
"'make -f output_dir/Makefile -i'.")
parser.add_argument('-q', '--quiet',
dest="quiet",
action='store_true',
default=argparse.SUPPRESS,
required=False,
help="Do not print the output or error of the "
"analyzers to the standard output of "
"CodeChecker.")
parser.add_argument('-c', '--clean',
dest="clean",
required=False,
action='store_true',
default=argparse.SUPPRESS,
help="Delete analysis reports stored in the output "
"directory. (By default, CodeChecker would keep "
"reports and overwrites only those files that "
"were update by the current build command).")
parser.add_argument('--compile-uniqueing',
type=str,
dest="compile_uniqueing",
default="none",
required=False,
help="Specify the method the compilation "
"actions in the compilation database are "
"uniqued before analysis. "
"CTU analysis works properly only if "
"there is exactly one "
"compilation action per source file. "
"none(default in non CTU mode): "
"no uniqueing is done. "
"strict: no uniqueing is done, "
"and an error is given if "
"there is more than one compilation "
"action for a source file. "
"symlink: recognizes symlinks and removes "
"duplication in the compilation database to "
"ensure that each source file is "
"analyzed only once. "
"alpha(default in CTU mode): If there is more "
"than one compilation action for a source "
"file, only the one is kept that belongs to the "
"alphabetically first "
"compilation target. "
"If none of the above given, "
"this parameter should "
"be a python regular expression. "
"If there is more than one compilation action "
"for a source, "
"only the one is kept which matches the "
"given python regex. If more than one "
"matches an error is given. "
"The whole compilation "
"action text is searched for match.")
parser.add_argument('--report-hash',
dest="report_hash",
default=argparse.SUPPRESS,
required=False,
choices=[
'context-free',
'context-free-v2',
'diagnostic-message'],
help="R|Specify the hash calculation method for "
"reports. By default the calculation method for "
"Clang Static Analyzer is context sensitive and "
"for Clang Tidy it is context insensitive.\n"
"You can use the following calculation methods:\n"
"- context-free: there was a bug and for Clang "
"Tidy not the context free hash was generated "
"(kept for backward compatibility).\n"
"- context-free-v2: context free hash is used "
"for ClangSA and Clang Tidy.\n"
"- diagnostic-message: context free hash with "
"bug step messages is used for ClangSA and "
"Clang Tidy.\n"
"See the 'issue hashes' section of the help "
"message of this command below for more "
"information.\n"
"USE WISELY AND AT YOUR OWN RISK!")
parser.add_argument('-n', '--name',
dest="name",
required=False,
default=argparse.SUPPRESS,
help="Annotate the run analysis with a custom name in "
"the created metadata file.")
analyzer_opts = parser.add_argument_group("analyzer arguments")
analyzer_opts.add_argument('--analyzers',
nargs='+',
dest='analyzers',
metavar='ANALYZER',
required=False,
choices=analyzer_types.supported_analyzers,
default=None,
help="Run analysis only with the analyzers "
"specified. Currently supported analyzers "
"are: " +
', '.join(analyzer_types.
supported_analyzers) + ".")
analyzer_opts.add_argument('--capture-analysis-output',
dest='capture_analysis_output',
action='store_true',
default=argparse.SUPPRESS,
required=False,
help="Store standard output and standard error "
"of successful analyzer invocations "
"into the '<OUTPUT_DIR>/success' "
"directory.")
analyzer_opts.add_argument('--generate-reproducer',
dest='generate_reproducer',
action='store_true',
default=argparse.SUPPRESS,
required=False,
help="Collect all necessary information for "
"reproducing an analysis action. The "
"gathered files will be stored in a "
"folder named 'reproducer' under the "
"report directory. When this flag is "
"used, 'failed' directory remains empty.")
cmd_config.add_option(analyzer_opts)
analyzer_opts.add_argument('--cppcheckargs',
dest="cppcheck_args_cfg_file",
required=False,
default=argparse.SUPPRESS,
help="DEPRECATED. "
"File containing argument which will be "
"forwarded verbatim for Cppcheck. The "
"option has been migrated under the "
"cppcheck anayzer options: "
"--analyzer-config "
"cppcheck:cc-verbatim-args-file="
"<filepath>")
analyzer_opts.add_argument('--saargs',
dest="clangsa_args_cfg_file",
required=False,
default=argparse.SUPPRESS,
help="DEPRECATED. "
"File containing argument which will be "
"forwarded verbatim for the Clang Static "
"Analyzer. The opion has been migrated "
"under the clangsa analyzer options: "
"--analyzer-config "
"clangsa:cc-verbatim-args-file=<filepath>")
analyzer_opts.add_argument('--tidyargs',
dest="tidy_args_cfg_file",
required=False,
default=argparse.SUPPRESS,
help="DEPRECATED. "
"File containing argument which will be "
"forwarded verbatim for Clang-Tidy. "
"The opion has been migrated under the "
"clang-tidy analyzer options: "
"--analyzer-config "
"clang-tidy:cc-verbatim-args-file="
"<filepath>")
analyzer_opts.add_argument('--tidy-config',
dest='tidy_config',
required=False,
default=argparse.SUPPRESS,
help="DEPRECATED. "
"A file in YAML format containing the "
"configuration of clang-tidy checkers. "
"The file can be dumped by "
"'CodeChecker analyzers --dump-config "
"clang-tidy' command.")
analyzer_opts.add_argument('--analyzer-config',
type=analyzer_config,
dest='analyzer_config',
nargs='*',
action=OrderedConfigAction,
default=[],
help="Analyzer configuration options in the "
"following format: analyzer:key=value. "
"The collection of the options can be "
"printed with "
"'CodeChecker analyzers "
"--analyzer-config'.\n"
"If the file at --tidyargs "
"contains a -config flag then those "
"options extend these.\n"
"To use an analyzer configuration file "
"in case of Clang Tidy (.clang-tidy) use "
"the "
"'clang-tidy:take-config-from-directory="
"true' option. It will skip setting the "
"'-checks' parameter of the clang-tidy "
"binary.")
analyzer_opts.add_argument('--checker-config',
type=checker_config,
dest='checker_config',
nargs='*',
action=OrderedConfigAction,
default=argparse.SUPPRESS,
help="Checker configuration options in the "
"following format: analyzer:key=value. "
"The collection of the options can be "
"printed with "
"'CodeChecker checkers --checker-config'.")
analyzer_opts.add_argument('--timeout',
type=int,
dest='timeout',
required=False,
default=argparse.SUPPRESS,
help="The amount of time (in seconds) that "
"each analyzer can spend, individually, "
"to analyze the project. If the analysis "
"of a particular file takes longer than "
"this time, the analyzer is killed and "
"the analysis is considered as a failed "
"one.")
analyzer_opts.add_argument('--z3',
dest='enable_z3',
choices=['on', 'off'],
default='off',
help="Enable Z3 as the solver backend. "
"This allows reasoning over more "
"complex queries, but performance is "
"much worse than the default "
"range-based constraint solver "
"system. WARNING: Z3 as the only "
"backend is a highly experimental "
"and likely unstable feature.")
clang_has_z3_refutation = analyzer_types.is_z3_refutation_capable()
analyzer_opts.add_argument('--z3-refutation',
dest='enable_z3_refutation',
choices=['on', 'off'],
default='on' if clang_has_z3_refutation
else 'off',
help="Switch on/off the Z3 SMT Solver "
"backend to "
"reduce false positives. The results "
"of the ranged based constraint "
"solver in the Clang Static Analyzer "
"will be cross checked with the Z3 "
"SMT solver. This should not cause "
"that much of a slowdown compared to "
"using only the Z3 solver.")
ctu_opts = parser.add_argument_group(
"cross translation unit analysis arguments",
"""
These arguments are only available if the Clang Static Analyzer supports
Cross-TU analysis. By default, no CTU analysis is run when
'CodeChecker analyze' is called.""")
ctu_modes = ctu_opts.add_mutually_exclusive_group()
ctu_modes.add_argument('--ctu', '--ctu-all',
action='store_const',
const=[True, True],
dest='ctu_phases',
default=argparse.SUPPRESS,
help="Perform Cross Translation Unit (CTU) "
"analysis, both 'collect' and 'analyze' "
"phases. In this mode, the extra files "
"created by 'collect' are cleaned up "
"after the analysis.")
ctu_modes.add_argument('--ctu-collect',
action='store_const',
const=[True, False],
dest='ctu_phases',
default=argparse.SUPPRESS,
help="Perform the first, 'collect' phase of "
"Cross-TU analysis. This phase generates "
"extra files needed by CTU analysis, and "
"puts them into '<OUTPUT_DIR>/ctu-dir'. "
"NOTE: If this argument is present, "
"CodeChecker will NOT execute the "
"analyzers!")
ctu_modes.add_argument('--ctu-analyze',
action='store_const',
const=[False, True],
dest='ctu_phases',
default=argparse.SUPPRESS,
help="Perform the second, 'analyze' phase of "
"Cross-TU analysis, using already "
"available extra files in "
"'<OUTPUT_DIR>/ctu-dir'. (These files "
"will not be cleaned up in this mode.)")
ctu_opts.add_argument('--ctu-reanalyze-on-failure',
action='store_true',
dest='ctu_reanalyze_on_failure',
default=argparse.SUPPRESS,
help="If Cross-TU analysis is enabled and fails "
"for some reason, try to re analyze the "
"same translation unit without "
"Cross-TU enabled.")
# Only check for AST loading modes if CTU is available.
ctu_opts.add_argument('--ctu-ast-mode',
action='store',
dest='ctu_ast_mode',
choices=['load-from-pch', 'parse-on-demand'],
default=argparse.SUPPRESS,
help="Choose the way ASTs are loaded during "
"CTU analysis. Mode 'load-from-pch' "
"generates PCH format serialized ASTs "
"during the 'collect' phase. Mode "
"'parse-on-demand' only generates the "
"invocations needed to parse the ASTs. "
"Mode 'load-from-pch' can use "
"significant disk-space for the "
"serialized ASTs, while mode "
"'parse-on-demand' can incur some "
"runtime CPU overhead in the second "
"phase of the analysis. NOTE: Only "
"available if CTU mode is enabled. "
"(default: parse-on-demand)")
stats_capable = analyzer_types.is_statistics_capable()
stat_opts = parser.add_argument_group(
"Statistics analysis feature arguments",
"""
These arguments are only available if the Clang Static Analyzer supports
Statistics-based analysis (e.g. statisticsCollector.ReturnValueCheck,
statisticsCollector.SpecialReturnValue checkers are available).""")
stat_opts.add_argument('--stats-collect', '--stats-collect',
action='store',
default=argparse.SUPPRESS,
dest='stats_output',
help="Perform the first, 'collect' phase of "
"Statistical analysis. This phase "
"generates extra files needed by "
"statistics analysis, and "
"puts them into "
"'<STATS_OUTPUT>'."
" NOTE: If this argument is present, "
"CodeChecker will NOT execute the "
"analyzers!")
stat_opts.add_argument('--stats-use', '--stats-use',
action='store',
default=argparse.SUPPRESS,
dest='stats_dir',
help="Use the previously generated statistics "
"results for the analysis from the given "
"'<STATS_DIR>'.")
stat_opts.add_argument('--stats',
action="store_true",
default=argparse.SUPPRESS,
dest='stats_enabled',
help="Perform both phases of "
"Statistical analysis. This phase "
"generates extra files needed by "
"statistics analysis and enables "
"the statistical checkers. "
"No need to enable them explicitly.")
stat_opts.add_argument('--stats-min-sample-count',
action='store',
default="10" if stats_capable
else argparse.SUPPRESS,
type=int,
dest='stats_min_sample_count',
help="Minimum number of samples (function call"
" occurrences) to be collected"
" for a statistics to be relevant "
"'<MIN-SAMPLE-COUNT>'.")
stat_opts.add_argument('--stats-relevance-threshold',
action='store',
default="0.85" if stats_capable
else argparse.SUPPRESS,
type=float,
dest='stats_relevance_threshold',
help="The minimum ratio of calls of function "
"f that must have a certain property "
"property to consider it true for that "
"function (calculated as calls "
"with a property/all calls)."
" CodeChecker will warn for"
" calls of f do not have that property."
"'<RELEVANCE_THRESHOLD>'.")
checkers_opts = parser.add_argument_group(
"checker configuration",
"""
Checkers
------------------------------------------------
An analyzer checks the source code with the help of checkers. Checkers
implement a specific rule, such as "don't divide by zero", and emit a warning
if the corresponding rule is violated. Available checkers can be listed by
'CodeChecker checkers'.
Checkers are grouped by CodeChecker via labels (described below), and sometimes
by their analyzer tool. An example for the latter is 'clangsa', which orders
checkers in a package hierarchy (e.g. in 'core.uninitialized.Assign', 'core'
and 'core.uninitialized' are packages).
Compiler warnings and errors
------------------------------------------------
Compiler warnings are diagnostic messages that report constructions that are
not inherently erroneous but that are risky or suggest there may have been an
error. However, CodeChecker views them as regular checkers.
Compiler warning names are transformed by CodeChecker to reflect the analyzer
name. For example, '-Wliteral-conversion' from clang-tidy is transformed to
'clang-diagnostic-literal-conversion'. However, they need to be enabled by
their original name, e.g. '-e Wliteral-conversion'.
Sometimes GCC is more permissive than Clang, so it is possible that a specific
construction doesn't compile with Clang but compiles with GCC. These
compiler errors are also collected as CodeChecker reports as
'clang-diagnostic-error'.
Note that compiler errors and warnings are captured by CodeChecker only if it
was emitted by clang-tidy.
Checker prefix groups
------------------------------------------------
Checker prefix groups allow you to enable checkers that share a common
prefix in their names. Checkers within a prefix group will have names that
start with the same identifier, making it easier to manage and reference
related checkers.
You can enable/disable checkers belonging to a checker prefix group:
'-e <label>:<value>', e.g. '-e prefix:security'.
Note: The 'prefix' label is mandatory when there is ambiguity between the
name of a checker prefix group and a checker profile or a guideline. This
prevents conflicts and ensures the correct checkers are applied.
See "CodeChecker checkers --help" to learn more.
Checker labels
------------------------------------------------
Each checker is assigned several '<label>:<value>' pairs. For instance,
'cppcheck-deallocret' has the labels 'profile:default' and 'severity:HIGH'. The
goal of labels is that you can enable or disable a batch of checkers with them.
You can enable/disable checkers belonging to a label: '-e <label>:<value>',
e.g. '-e profile:default'.
Note: The 'profile' label is mandatory when there is ambiguity between the
name of a checker profile and a checker prefix group or a guideline. This
prevents conflicts and ensures the correct checkers are applied.
See "CodeChecker checkers --help" to learn more.
Guidelines
------------------------------------------------
CodeChecker recognizes several third party coding guidelines, such as
CppCoreGuidelines, SEI-CERT, or MISRA. These are collections of best
programming practices to avoid common programming errors. Some checkers cover
the rules of these guidelines. CodeChecker assigns the 'guideline' label to
these checkers, such as 'guideline:sei-cert'. This way you can list and enable
those checkers which check the fulfillment of certain guideline rules. See the
output of "CodeChecker checkers --guideline" command.
Guidelines are labels themselves, and can be used as a label:
'-e guideline:<value>', e.g. '-e guideline:sei-cert'.
Note: The 'guideline' label is mandatory when there is ambiguity between the
name of a guideline and a checker prefix group or a checker profile. This
prevents conflicts and ensures the correct checkers are applied.
Batch enabling/disabling checkers
------------------------------------------------
You can fine-tune which checkers to use in the analysis by setting the enable
and disable flags starting from the bigger groups and going inwards. Taking
for example the package hierarchy of 'clangsa', '-e core -d core.uninitialized
-e core.uninitialized.Assign' will enable every 'core' checker, but only
'core.uninitialized.Assign' from the 'core.uninitialized' group. Mind that
disabling certain checkers - such as the 'core' group is unsupported by the
LLVM/Clang community, and thus discouraged.
""")
checkers_opts.add_argument('-e', '--enable',
dest="enable",
metavar='checker/group/profile',
default=argparse.SUPPRESS,
action=OrderedCheckersAction,
help="Set a checker (or checker prefix group), "
"profile or guideline to BE USED in the "
"analysis. Labels can also be "
"used for selecting checkers, for example "
"profile:extreme or severity:STYLE. See "
"'CodeChecker checkers --label' for "
"further details. In case of a name clash "
"between the checker prefix "
"group/profile/guideline name, the use of "
"one of the following labels is "
"mandatory: 'checker:', 'prefix:', "
"'profile:', 'guideline:'. If a checker "
"name matches multiple checkers as a "
"prefix, 'checker:' or 'prefix:' "
"namespace is required")
checkers_opts.add_argument('-d', '--disable',
dest="disable",
metavar='checker/group/profile',
default=argparse.SUPPRESS,
action=OrderedCheckersAction,
help="Set a checker (or checker prefix group), "
"profile or guideline "
"to BE PROHIBITED from use in the "
"analysis. Labels can also be "
"used for selecting checkers, for example "
"profile:extreme or severity:STYLE. See "
"'CodeChecker checkers --label' for "
"further details. In case of a name clash "
"between the checker prefix "
"group/profile/guideline name, the use of "
"one of the following labels is "
"mandatory: 'checker:', 'prefix:', "
"'profile:', 'guideline:'. If a checker "
"name matches multiple checkers as a "
"prefix, 'checker:' or 'prefix:' "
"namespace is required")
checkers_opts.add_argument('--enable-all',
dest="enable_all",
action='store_true',
required=False,
default=argparse.SUPPRESS,
help="Force the running analyzers to use "
"almost every checker available. The "
"checker groups 'alpha.', 'debug.',"
"'osx.', 'abseil-', 'android-', "
"'darwin-', 'objc-', "
"'cppcoreguidelines-', 'fuchsia.', "
"'fuchsia-', 'hicpp-', 'llvm-', "
"'llvmlibc-', 'google-', 'zircon-', "
"'osx.' (on Linux) are NOT enabled "
"automatically and must be EXPLICITLY "
"specified. WARNING! Enabling all "
"checkers might result in the analysis "
"losing precision and stability, and "
"could even result in a total failure of "
"the analysis. USE WISELY AND AT YOUR "
"OWN RISK!")
checkers_opts.add_argument('--disable-all',
dest="disable_all",
required=False,
default=argparse.SUPPRESS,
action='store_true',
help="Disable all checkers of all analyzers. "
"It is equivalent to using \"--disable "
"default\" as the first argument.")
checkers_opts.add_argument('--no-missing-checker-error',
dest="no_missing_checker_error",
action='store_true',
required=False,
default=argparse.SUPPRESS,
help="Emit a warning instead of an error when "
"an unknown checker name is given to "
"either --enable, --disable,"
"--analyzer-config and/or "
"--checker-config.")
logger.add_verbose_arguments(parser)
parser.set_defaults(
func=main, func_process_config_file=cmd_config.process_config_file)
def is_analyzer_config_valid(
args,
analyzer_config_args: List[AnalyzerConfigArg]
) -> bool:
"""
Ensure that the analyzer_config parameter is set to a valid value
by verifying if it belongs to the set of allowed values.
"""
wrong_config_messages = []
available_analyzers = {}
for analyzer_name, analyzer_class in \
analyzer_types.supported_analyzers.items():
if analyzer_class.get_binary_version() is not None:
available_analyzers[analyzer_name] = analyzer_class
enabled_analyzers = {}
if args.analyzers:
enabled_analyzer_names = \
set(args.analyzers).intersection(available_analyzers)
enabled_analyzers = {
analyzer_name: available_analyzers[analyzer_name]
for analyzer_name in enabled_analyzer_names
}
if enabled_analyzers:
available_analyzers = enabled_analyzers
analyzer_configs = {}
for analyzer_name, analyzer_class in available_analyzers.items():
try:
analyzer_configs[analyzer_name] = \
analyzer_class.get_analyzer_config()
except Exception as e:
wrong_config_messages.append(
f"Could not get config for analyzer '{analyzer_name}'. "
f"Error: {e}")
continue
for cfg_arg in analyzer_config_args:
if enabled_analyzers and cfg_arg.analyzer not in enabled_analyzers:
wrong_config_messages.append(
f"The analyzer '{cfg_arg.analyzer}' is not enabled. Enable it "
"first using --analyzers to set the config "
f"'{cfg_arg.option}'.")
continue
if cfg_arg.analyzer not in available_analyzers:
wrong_config_messages.append(
f"Invalid argument to --analyzer-config: '{cfg_arg.analyzer}' "
f"is not an available analyzer. Available analyzers are: "
f"{', '.join(a for a in available_analyzers)}.")
continue
try:
analyzer_cfg = next(
(x for x in analyzer_configs[cfg_arg.analyzer]
if x.option == cfg_arg.option),
None)
except Exception:
wrong_config_messages.append(
f"The analyzer '{cfg_arg.analyzer}' is not found! Make sure "
"it is loaded or exists with the command "
"'CodeChecker analyzers'"
)
continue
if analyzer_cfg is None:
wrong_config_messages.append(
f"Invalid argument to --analyzer-config: {cfg_arg.analyzer} "
f"has no config named '{cfg_arg.option}'. Use the "
f"'CodeChecker analyzers --analyzer-config "
f"{cfg_arg.analyzer}' command to see available configs.")
else:
try:
analyzer_cfg.value_type(cfg_arg.value)
except Exception as ex:
wrong_config_messages.append(
f"Invalid value to --analyzer-config: "
f"'{cfg_arg.analyzer}:{cfg_arg.option}={cfg_arg.value}'. "
f"{ex}")
if wrong_config_messages:
for wrong_config_message in wrong_config_messages:
LOG.error(wrong_config_message)
return False
return True
def is_checker_config_valid(
checker_config_args: List[CheckerConfigArg]
) -> bool:
"""
Ensure that the checker_config parameter is set to a valid value
by verifying if it belongs to the set of allowed values.
"""
wrong_config_messages = []
supported_analyzers = analyzer_types.supported_analyzers
checker_configs = {
analyzer_name: analyzer_class.get_checker_config()
for analyzer_name, analyzer_class
in supported_analyzers.items()
}
for cfg_arg in checker_config_args:
if cfg_arg.analyzer not in supported_analyzers:
wrong_config_messages.append(
f"Invalid argument to --checker-config: '{cfg_arg.analyzer}' "
f"is not a supported analyzer. Supported analyzers are: "
f"{', '.join(a for a in supported_analyzers)}.")
continue
checker_cfg = next(
(x for x in checker_configs[cfg_arg.analyzer]
if x.checker == cfg_arg.checker and x.option == cfg_arg.option),
None)
if checker_cfg is None:
wrong_config_messages.append(
f"Invalid argument to --checker-config: invalid checker "
f"'{cfg_arg.checker}' and/or checker option "
f"'{cfg_arg.option}' for {cfg_arg.analyzer}. Use the "