Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not allowing disabling modeling checkers in ClangSA #3323

Merged
merged 1 commit into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ def get_analyzer_checkers(
"""Return the list of the supported checkers."""
checker_list_args = clang_options.get_analyzer_checkers_cmd(
cfg_handler,
alpha=True)
alpha=True,
debug=False)
return parse_clang_help_page(checker_list_args, 'CHECKERS:', environ)

@classmethod
Expand Down Expand Up @@ -227,16 +228,23 @@ def construct_analyzer_cmd(self, result_handler):
['-Xclang', '-analyzer-config', '-Xclang', cfg])

# Config handler stores which checkers are enabled or disabled.
disabled_checkers = []
enabled_checkers = []
for checker_name, value in config.checks().items():
state, _ = value
if state == CheckerState.enabled:
analyzer_cmd.extend(['-Xclang',
'-analyzer-checker=' + checker_name])
enabled_checkers.append(checker_name)
elif state == CheckerState.disabled:
analyzer_cmd.extend(['-Xclang',
'-analyzer-disable-checker=' +
checker_name])
disabled_checkers.append(checker_name)

if enabled_checkers:
analyzer_cmd.extend(['-Xclang',
'-analyzer-checker=' +
','.join(enabled_checkers)])
if disabled_checkers:
analyzer_cmd.extend(['-Xclang',
'-analyzer-disable-checker=' +
','.join(disabled_checkers)])
# Enable aggressive-binary-operation-simplification option.
analyzer_cmd.extend(
clang_options.get_abos_options(config.version_info))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
LOG = get_logger('analyzer')


def get_analyzer_checkers_cmd(cfg_handler, alpha=True, debug=True):
def get_analyzer_checkers_cmd(cfg_handler, alpha=True, debug=False):
dkrupp marked this conversation as resolved.
Show resolved Hide resolved
"""Return the checkers list getter command which depends on the used clang
version.

Expand Down
36 changes: 36 additions & 0 deletions analyzer/tests/functional/analyze/test_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def setUp(self):
self.missing_checker_regex = re.compile(
r"No checker\(s\) with these names was found")

self.disabling_modeling_checker_regex = re.compile(
r"analyzer-disable-checker=.*unix.cstring.CStringModeling.*")

def tearDown(self):
"""Restore environment after tests have ran."""
os.chdir(self.__old_pwd)
Expand Down Expand Up @@ -850,6 +853,39 @@ def test_invalid_disabled_checker_name(self):
errcode = process.returncode
self.assertEqual(errcode, 0)

def test_disabling_clangsa_modeling_checkers(self):
"""Warn in case a modeling checker is disabled from clangsa"""
build_json = os.path.join(self.test_workspace, "build_success.json")
analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "clangsa", "-o", self.report_dir,
"-d", "unix", "--verbose", "debug_analyzer"]

source_file = os.path.join(self.test_dir, "success.c")
build_log = [{"directory": self.test_workspace,
"command": "gcc -c " + source_file,
"file": source_file
}]

with open(build_json, 'w',
encoding="utf-8", errors="ignore") as outfile:
json.dump(build_log, outfile)

print(analyze_cmd)
process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, _ = process.communicate()

match = self.disabling_modeling_checker_regex.search(out)
self.assertIsNone(match)

errcode = process.returncode
self.assertEqual(errcode, 0)

def test_multiple_invalid_checker_names(self):
"""Warn in case of multiple invalid checker names."""
build_json = os.path.join(self.test_workspace, "build_success.json")
Expand Down
12 changes: 6 additions & 6 deletions analyzer/tests/functional/ctu_failure/test_ctu_failure.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def test_ctu_failure_zip(self):
# with a specified name is analyzed.
output, result = self.__do_ctu_all(
on_demand=False, extra_args=["--verbose", "debug",
"-e", "debug.ExprInspection"])
"--saargs", "./ctu_failure.saargs"])
dkrupp marked this conversation as resolved.
Show resolved Hide resolved
self.assertEqual(result, 3, "Analyzer survived the failure.")

# lib.c should be logged as its AST is loaded by Clang
Expand Down Expand Up @@ -185,7 +185,7 @@ def test_ctu_on_demand_failure_zip(self):
# with a specified name is analyzed.
output, result = self.__do_ctu_all(
on_demand=True, extra_args=["--verbose", "debug",
"-e", "debug.ExprInspection"])
"--saargs", "./ctu_failure.saargs"])
self.assertEqual(result, 3, "Analyzer survived the failure.")

# lib.c should be logged as its AST is loaded by Clang
Expand Down Expand Up @@ -235,7 +235,7 @@ def test_ctu_failure_zip_with_headers(self):
# with a specified name is analyzed.
output, result = self.__do_ctu_all(
on_demand=False, extra_args=["--verbose", "debug",
"-e", "debug.ExprInspection"])
"--saargs", "./ctu_failure.saargs"])
self.assertEqual(result, 3, "Analyzer survived the failure.")

# lib.c should be logged as its AST is loaded by Clang
Expand Down Expand Up @@ -287,7 +287,7 @@ def test_ctu_on_demand_failure_zip_with_headers(self):
# with a specified name is analyzed.
output, result = self.__do_ctu_all(
on_demand=True, extra_args=["--verbose", "debug",
"-e", "debug.ExprInspection"])
"--saargs", "./ctu_failure.saargs"])
self.assertEqual(result, 3, "CTU analyzing should fail.")

# lib.c should be logged as its AST is loaded by Clang
Expand Down Expand Up @@ -334,7 +334,7 @@ def test_ctu_fallback(self):

output, result = self.__do_ctu_all(
on_demand=False, extra_args=["--verbose", "debug",
"-e", "debug.ExprInspection",
"--saargs", "./ctu_failure.saargs",
"--ctu-reanalyze-on-failure"])
self.assertEqual(result, 3, "CTU analyzing should fail.")

Expand Down Expand Up @@ -362,7 +362,7 @@ def test_ctu_on_demand_fallback(self):

output, result = self.__do_ctu_all(
on_demand=True, extra_args=["--verbose", "debug",
"-e", "debug.ExprInspection",
"--saargs", "./ctu_failure.saargs",
"--ctu-reanalyze-on-failure"])
self.assertEqual(result, 3, "CTU analyzing should fail.")

Expand Down
1 change: 1 addition & 0 deletions analyzer/tests/projects/ctu_failure/ctu_failure.saargs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-Xclang -analyzer-checker=debug.ExprInspection
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-Xclang -analyzer-checker=debug.ExprInspection
119 changes: 71 additions & 48 deletions docs/analyzer/checker_and_analyzer_configuration.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
# Configure Clang Static Analyzer and checkers

Analyzer configuration can be done through the `--saargs` analysis option which
forwards arguments without modification to the Clang Static Analyzer:
## Analyzer Configuration <a name="analyzer-configuration"></a>

The analysis can be configured using analyzer wide configuration parameters.
These parameters may have effect on the whole analysis, affecting the result of
all checkers.

Listing the available configuration options:
`CodeChecker analyzers --analyzer-config clangsa --details`

Setting analyzer configuration opions:
`CodeChecker analyze --analyzer-config <key=value>`

You can find a comprehensive list of analyzer configuration options at the
[clang static analyzer
documentation](https://github.com/llvm-mirror/clang/tree/master/docs) pages.

## Checker Configuration <a name="checker-configuration"></a>

Clang Static Analyzer checkers can be enabled and disabled using the
`CodeChekcer analyze --enable <checker_name> --disable <checker_name>` flags.
You can list/enable/disable all checkers for Clang Static Analyzer, except for
the developer (debug and modeling) checkers.

Some checkers can be customized using checker specific configuration options.

These can be listed using the `CodeChecker checkers --checker-config` command
and can be set by `CodeChecker analyze --checker-config
clangsa:<option-name>=<value>`.

You can find the documentation of the configuration options at hte [Clang Static
Analyzer
checkers](https://github.com/llvm-mirror/clang/tree/master/lib/StaticAnalyzer/Checkers)
page.

## Clang Static Analyzer Special Configuration Options
In special cases, when the checker and analyzer configurability that is provided
by CodeChecker is not enough, the Clang Static analyzer configuration can be
extended through the `--saargs` analysis option. The content of the saargs file
are forwarded as arguments without modification to the Clang Static Analyzer:
```
CodeChecker analyze --saargs static_analyzer.cfg
```
Expand All @@ -12,57 +49,25 @@ configuration options can be configured like this:
-Xclang -analyzer-config -Xclang unix.Malloc:Optimistic=true -Xclang -analyzer-max-loop -Xclang 20
```
__Before every configuration option '-Xclang' argument should be written and
all the configuration options sould be in one line!__
all the configuration options sould be in one line! __

In the `static_analyzer.cfg` example file we set a checker specific
configuration option `unix.Malloc:Optimistic=true` for the `unix.Malloc`
checker and a static analyzer configuration option `analyzer-max-loop` (the
maximum number of times the analyzer will go through a loop, the default
value is 4).

## Checker specific configuration options
This is not a comprehensive list view checker
[documentation or implementation](https://github.com/llvm-mirror/clang/tree/master/lib/StaticAnalyzer/Checkers)
for available configuration options:

| checker name | configuration option | default value | available values | description |
|--------------|--------------------------------|---------------|------------------|----------------------------------------------------------------------------------------|
| nullability | NoDiagnoseCallsToSystemHeaders | false | true/false | If true, the checker will not diagnose nullability issues for calls to system headers. |
| unix.Malloc | Optimistic | false | true/false | |


## Clang Static Analyzer configuration options
This is not a comprehesive list, check out the
[clang static analyzer documentation](https://github.com/llvm-mirror/clang/tree/master/docs)
or source code for more details about the configuration options.

| configuration option | default value | available values | description |
|---------------------------------------|-------------------|------------------------------------------|-----------------------------------------------------------------------------------------------------|
| analyzer-max-loop | 4 | | |
| inline-lambdas | true | | |
| ipa | dynamic-bifurcate | | [inter procedural analysis](https://github.com/llvm-mirror/clang/blob/master/docs/analyzer/IPA.txt) |
| ipa-always-inline-size | 3 | | |
| mode | deep | deep, shallow | |
| max-inlinable-size | 100 | | 100 for deep mode, 4 for shallow |
| max-nodes | 225000 | | 22500 for deep, 75000 for shallow, maximum number of nodes for top level functions |
| unroll-loops | false | true/false | |
| widen-loops | false | true/false | |
| suppress-null-return-paths | false | | |
| c++-inlining | constructors | constructors, destructors, none, methods | [inlining options](https://github.com/llvm-mirror/clang/blob/master/docs/analyzer/IPA.txt) |
| leak-diagnostics-reference-allocation | false | true/false | |
| max-times-inline-large | 32 | | |
| region-store-small-struct-limit | 2 | | |
| path-diagnostics-alternate | false | true/false | |
| report-in-main-source-file | true | true/false | |
| min-cfg-size-treat-functions-as-large | 14 | | |
| cfg-conditional-static-initializers | true | | |
| cfg-implicit-dtors | true | true/false | |
| cfg-lifetime | false | true/false | |
| cfg-loopexit | false | true/false | |
| cfg-temporary-dtors | false | true/false | |
| faux-bodies | true | true/false | |
| graph-trim-interval | 1000 | | |
### Enabling developer checkers
You cannot enable/disable developer checkers in CodeChecker using the `--enable`
or `--disable` flags.

These (debug and modeling) checkers should not be used normally. They are
typically used by ClangSA developers debug the analysis or to write test cases.
These checkers can be listed by `clang -cc1 -analyzer-checker-help-developer`.

If they are needed, they can be switched on using the following command
`CodeChecker analyzer --saarg saarg.config`, where the content of saarg.config
is for example `-Xclang -analyzer-checker=debug.ExprInspection`.

## Z3 Theorem Prover
The static analyzer supports using the
Expand Down Expand Up @@ -97,14 +102,32 @@ command with the `--z3-refutation` option.
You can read more about refutation with the Z3 SMT Solver
[here](https://docs.google.com/document/d/1-HEblH92VxdxDp04vDKjFa4_ZL9l2oPVLFtQUfLKSOo/).

# Configure Clang tidy checkers
# Configuring Clang-Tidy

## Configuring the analyzer and checkers

## Using Clang tidy configuration files
You can configure the clang-tidy analyzer and its checkers through CodeChecker
with the `--analyzer-config` and the `--checker-config` flags of `CodeChecker
analyze/check` commands as described in sections [Analyzer
Configuration](#analyzer-configuration) and [Checker
Configuration](#checker-configuration).

__clang-tidy__ attempts to read configuration for each analyzed source file

## Using Clang-Tidy configuration files

If you want to control the configuration of clang-tidy from the `.clang-tidy`
configuration files (instead of the CodeChecker command line) you can use the
`clang-tidy:take-config-from-directory=true` option. It will skip setting the
checkers and checker configuration from CodeChecker (even if a profile was
specified).

Then __clang-tidy__ will attempt to read configuration for each analyzed source file
from a `.clang-tidy` file located in the closest parent directory of the
analyzed source file.

So by executing `CodeChecker analyze compile_commands.json -o ./reports --analyzer-config 'clang-tidy:take-config-from-directory=true'`, CodeChecker will generate a clang-tidy command which will NOT
contain the -checks option at all so your .clang-tidy file will take precedence.

The `.clang-tidy` configuration file can be in JSON or YAML format.

JSON:
Expand Down