Skip to content

Commit

Permalink
Merge pull request Ericsson#4315 from bruntib/isystem_vs_idirafter
Browse files Browse the repository at this point in the history
[feat] Implicit include paths added with -idirafter
  • Loading branch information
dkrupp authored Aug 16, 2024
2 parents fc37bf7 + 2df162b commit b60576d
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 26 deletions.
7 changes: 6 additions & 1 deletion analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,8 @@ def construct_analyzer_cmd(self, result_handler):
analyzer_cmd.extend(self.buildaction.analyzer_options)

analyzer_cmd.extend(prepend_all(
'-isystem',
'-isystem' if config.add_gcc_include_dirs_with_isystem else
'-idirafter',
self.buildaction.compiler_includes))

analyzer_cmd.append(self.source_file)
Expand Down Expand Up @@ -620,6 +621,10 @@ def construct_config_handler(cls, args):
handler.enable_z3_refutation = 'enable_z3_refutation' in args and \
args.enable_z3_refutation == 'on'

handler.add_gcc_include_dirs_with_isystem = \
'add_gcc_include_dirs_with_isystem' in args and \
args.add_gcc_include_dirs_with_isystem

if 'ctu_phases' in args:
handler.ctu_dir = os.path.join(args.output_path,
args.ctu_dir)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ def get_compile_command(action, config, source='', output=''):
# -isystem, etc. flags where it is found. For this reason we append the
# implicit include paths to the end of the analyzer command in order to get
# less precedence than the user's explicit include paths.
cmd.extend(prepend_all('-isystem', action.compiler_includes))
cmd.extend(prepend_all(
'-isystem' if config.add_gcc_include_dirs_with_isystem else
'-idirafter',
action.compiler_includes))
if output:
cmd.extend(['-o', output])
if source:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ def build_stat_coll_cmd(action, config, source):
if not has_flag('-std', cmd) and not has_flag('--std', cmd):
cmd.append(action.compiler_standard)

cmd.extend(prepend_all('-isystem', action.compiler_includes))
cmd.extend(prepend_all(
'-isystem' if config.add_gcc_include_dirs_with_isystem else
'-idirafter',
action.compiler_includes))

if source:
cmd.append(source)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ def construct_analyzer_cmd(self, result_handler):
analyzer_cmd.extend(self.buildaction.analyzer_options)

analyzer_cmd.extend(prepend_all(
'-isystem',
'-isystem' if config.add_gcc_include_dirs_with_isystem else
'-idirafter',
self.buildaction.compiler_includes))

if not has_flag('-std', analyzer_cmd) and not \
Expand Down Expand Up @@ -585,6 +586,10 @@ def construct_config_handler(cls, args):
handler.report_hash = args.report_hash \
if 'report_hash' in args else None

handler.add_gcc_include_dirs_with_isystem = \
'add_gcc_include_dirs_with_isystem' in args and \
args.add_gcc_include_dirs_with_isystem

# FIXME We cannot get the resource dir from the clang-tidy binary,
# therefore we get a sibling clang binary which of clang-tidy.
# TODO Support "clang-tidy -print-resource-dir" .
Expand Down
11 changes: 11 additions & 0 deletions analyzer/codechecker_analyzer/cmd/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,17 @@ def add_arguments_to_parser(parser):
"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,
Expand Down
12 changes: 12 additions & 0 deletions analyzer/codechecker_analyzer/cmd/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ def add_arguments_to_parser(parser):
"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.")

log_args = parser.add_argument_group(
"log arguments",
"""
Expand Down Expand Up @@ -896,6 +907,7 @@ def __update_if_key_exists(source, target, key):
'review_status_config',
'compile_uniqueing',
'report_hash',
'add_gcc_include_dirs_with_isystem',
'enable_z3',
'enable_z3_refutation']
for key in args_to_update:
Expand Down
2 changes: 1 addition & 1 deletion analyzer/tests/functional/analyze/test_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def test_compiler_info_file_is_loaded(self):
print(out)
self.assertTrue("-std=FAKE_STD" in out)
self.assertTrue("--target=FAKE_TARGET" in out)
self.assertTrue("-isystem /FAKE_INCLUDE_DIR" in out)
self.assertTrue("-idirafter /FAKE_INCLUDE_DIR" in out)

def test_capture_analysis_output(self):
"""
Expand Down
33 changes: 33 additions & 0 deletions analyzer/tests/libtest/cmd_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -------------------------------------------------------------------------
#
# 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
#
# -------------------------------------------------------------------------

import argparse
from codechecker_analyzer.cmd import analyze


class NoExitArgumentParser(argparse.ArgumentParser):
"""
ArgumentParser that does not exit on error.
"""
def error(self, _):
pass


def create_analyze_argparse(args=None):
"""
Create argparse object for analyze command.
:param args: list of command line arguments to parse.
"""
if args is None:
args = []

parser = NoExitArgumentParser()
analyze.add_arguments_to_parser(parser)

return parser.parse_args(args)
65 changes: 65 additions & 0 deletions analyzer/tests/unit/test_analyzer_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -------------------------------------------------------------------------
#
# 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
#
# -------------------------------------------------------------------------

import argparse
import unittest
from codechecker_analyzer.analyzers.clangsa.analyzer import ClangSA
from codechecker_analyzer.buildlog import log_parser
from codechecker_analyzer.cmd import analyze
from libtest.cmd_line import create_analyze_argparse


def create_analyzer_sa(args=None):
parser = argparse.ArgumentParser()
analyze.add_arguments_to_parser(parser)
cfg_handler = ClangSA.construct_config_handler(
create_analyze_argparse(args))

action = {
'file': 'main.cpp',
'command': "g++ -o main main.cpp",
'directory': '/'}
build_action = log_parser.parse_options(action)

return ClangSA(cfg_handler, build_action)


def create_result_handler(analyzer):
"""
Create result handler for construct_analyzer_cmd call.
"""

build_action = analyzer.buildaction

rh = analyzer.construct_result_handler(
build_action,
build_action.directory,
None)

rh.analyzed_source_file = build_action.source

return rh


class AnalyzerCommandClangSATest(unittest.TestCase):
def test_isystem_idirafter(self):
"""
Test that the implicit include paths are added to the analyzer command
with -idirafter.
"""
analyzer = create_analyzer_sa(['--add-gcc-include-dirs-with-isystem'])

result_handler = create_result_handler(analyzer)
cmd = analyzer.construct_analyzer_cmd(result_handler)
self.assertIn('-isystem', cmd)

analyzer = create_analyzer_sa()

result_handler = create_result_handler(analyzer)
cmd = analyzer.construct_analyzer_cmd(result_handler)
self.assertIn('-idirafter', cmd)
34 changes: 13 additions & 21 deletions analyzer/tests/unit/test_checker_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
from codechecker_analyzer import analyzer_context
from codechecker_analyzer.buildlog import log_parser

from libtest.cmd_line import create_analyze_argparse


class MockClangsaCheckerLabels:
def checkers_by_labels(self, labels):
Expand Down Expand Up @@ -68,8 +70,7 @@ def checkers(self, _=None):


def create_analyzer_sa():
args = []
cfg_handler = ClangSA.construct_config_handler(args)
cfg_handler = ClangSA.construct_config_handler(create_analyze_argparse())

action = {
'file': 'main.cpp',
Expand Down Expand Up @@ -146,7 +147,7 @@ def f(checks, checkers):
return set(checkers) <= result
return f

args = []
args = create_analyze_argparse()

# "security" profile, but alpha -> not in default.
security_profile_alpha = [
Expand Down Expand Up @@ -333,10 +334,8 @@ def occurring_values(self, label):


def create_analyzer_tidy(args=None):
if args is None:
args = []

cfg_handler = ClangTidy.construct_config_handler(args)
cfg_handler = ClangTidy.construct_config_handler(
create_analyze_argparse(args))

action = {
'file': 'main.cpp',
Expand Down Expand Up @@ -430,9 +429,7 @@ def test_disable_clangsa_checkers(self):
self.assertTrue(is_compiler_warning('Wreserved-id-macro'))
self.assertFalse(is_compiler_warning('hicpp'))

args = Namespace()
args.ordered_checkers = [('Wreserved-id-macro', True)]
analyzer = create_analyzer_tidy(args)
analyzer = create_analyzer_tidy(['--enable', 'Wreserved-id-macro'])
result_handler = create_result_handler(analyzer)

analyzer.config_handler.checker_config = '{}'
Expand Down Expand Up @@ -493,11 +490,9 @@ def test_enable_all_disable_warning(self):
Side note: we use -Weverything instead of listing all enabled warnings
to represent --enable-all.
"""
args = Namespace()
args.ordered_checkers = [('clang-diagnostic-unused-variable', False)]
args.enable_all = True

analyzer = create_analyzer_tidy(args)
analyzer = create_analyzer_tidy([
'--enable-all',
'--disable', 'clang-diagnostic-unused-variable'])
result_handler = create_result_handler(analyzer)

analyzer_cmd = analyzer.construct_analyzer_cmd(result_handler)
Expand Down Expand Up @@ -535,13 +530,10 @@ def test_clang_diags_as_compiler_warnings(self):
Test that clang-diagnostic-* checkers are enabled as compiler warnings.
"""

args = Namespace()
args.ordered_checkers = [
analyzer = create_analyzer_tidy([
# This should enable -Wvla and -Wvla-extension.
('clang-diagnostic-vla', True),
('clang-diagnostic-unused-value', False)
]
analyzer = create_analyzer_tidy(args)
'--enable', 'clang-diagnostic-vla',
'--disable', 'clang-diagnostic-unused-value'])
result_handler = create_result_handler(analyzer)

analyzer.config_handler.checker_config = '{}'
Expand Down
20 changes: 20 additions & 0 deletions docs/analyzer/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ subcommand.
```
usage: CodeChecker check [-h] [-o OUTPUT_DIR] [-t {plist}] [-q]
[--keep-gcc-include-fixed] [--keep-gcc-intrin]
[--add-gcc-include-dirs-with-isystem]
(-b COMMAND | -l LOGFILE) [-j JOBS] [-c]
[--compile-uniqueing COMPILE_UNIQUEING]
[--report-hash {context-free,context-free-v2,diagnostic-message}]
Expand Down Expand Up @@ -179,6 +180,11 @@ optional arguments:
be kept among the implicit include paths. Use this
flag if Clang analysis fails with error message
related to __builtin symbols. (default: False)
--add-gcc-include-dirs-with-isystem
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. (default: False)
--compile-uniqueing COMPILE_UNIQUEING
Specify the method the compilation actions in the
compilation database are uniqued before analysis. CTU
Expand Down Expand Up @@ -931,6 +937,7 @@ usage: CodeChecker analyze [-h] [-j JOBS]
OUTPUT_PATH
[--compiler-info-file COMPILER_INFO_FILE]
[--keep-gcc-include-fixed] [--keep-gcc-intrin]
[--add-gcc-include-dirs-with-isystem]
[-t {plist}] [-q] [-c]
[--compile-uniqueing COMPILE_UNIQUEING]
[--report-hash {context-free,context-free-v2,diagnostic-message}]
Expand Down Expand Up @@ -990,6 +997,11 @@ optional arguments:
be kept among the implicit include paths. Use this
flag if Clang analysis fails with error message
related to __builtin symbols. (default: False)
--add-gcc-include-dirs-with-isystem
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. (default: False)
-t {plist}, --type {plist}, --output-format {plist}
Specify the format the analysis results should use.
(default: plist)
Expand Down Expand Up @@ -1384,6 +1396,14 @@ analysis unless `--keep-gcc-include-fixed` or `--keep-gcc-intrin` flag is
given. For further information see
[GCC incompatibilities](gcc_incompatibilities.md).

The GCC compiler's implicit include directories are appended to the analyzer
command with `-idirafter`. There are other flags which can be used instead of
`-idirafter`, such as , `-I`, `-isystem`, etc. They have a
[priority order](https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html) in
which compilers search header files. Prior to CodeChecker 6.24.1, the
`-isystem` flag was used instead of `-idirafter`. If you need to the `-isystem`
flag, you can use the `--add-gcc-include-dirs-with-isystem` flag.

#### Toggling checkers

The list of checkers to be used in the analysis can be fine-tuned with the
Expand Down

0 comments on commit b60576d

Please sign in to comment.