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

[bugfix] Allow the disabling of statisticsbased checkers #3972

Merged
merged 1 commit into from
Sep 1, 2023
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
21 changes: 0 additions & 21 deletions analyzer/codechecker_analyzer/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@

from codechecker_common.logger import get_logger

from codechecker_statistics_collector.collectors.special_return_value import \
SpecialReturnValueCollector
from codechecker_statistics_collector.collectors.return_value import \
ReturnValueCollector

from . import analyzer_context, analysis_manager, pre_analysis_manager, \
checkers
from .analyzers import analyzer_types
Expand Down Expand Up @@ -193,22 +188,6 @@ def perform_analysis(args, skip_handlers, actions, metadata_tool,
"'--no-missing-checker-error'")
sys.exit(1)

if 'stats_enabled' in args:
config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
SpecialReturnValueCollector.checker_analyze)

config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
ReturnValueCollector.checker_analyze)

# Statistics collector checkers must be explicitly disabled
# as they trash the output.
if "clangsa" in analyzers:
config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
SpecialReturnValueCollector.checker_collect, False)

config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
ReturnValueCollector.checker_collect, False)

enabled_checkers = defaultdict(list)

# Save some metadata information.
Expand Down
51 changes: 51 additions & 0 deletions analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
from codechecker_common.logger import get_logger

from codechecker_analyzer import analyzer_context, env
from codechecker_statistics_collector.collectors.special_return_value import \
SpecialReturnValueCollector
from codechecker_statistics_collector.collectors.return_value import \
ReturnValueCollector

from .. import analyzer_base
from ..config_handler import CheckerState
Expand Down Expand Up @@ -94,6 +98,19 @@ def parse_clang_help_page(
return res


def _is_user_disabled_checker(checker, ordered_checkers):
"""
This function returns True if the given checker is disabled by the user
explicitly by a --disable flag.
"""
if not ordered_checkers:
return False

disabled_checkers = (c for c, enabled in ordered_checkers if not enabled)

return any(checker.startswith(c) for c in disabled_checkers)


class ClangSA(analyzer_base.SourceAnalyzer):
"""
Constructs clang static analyzer commands.
Expand Down Expand Up @@ -596,6 +613,40 @@ def construct_config_handler(cls, args):
cmdline_checkers,
'enable_all' in args and args.enable_all)

# If --stats flag is provided then enable statistics-based checkers
# unless explicitly disabled by the user.
if 'stats_enabled' in args:
# In some Clang versions, statisticsbased checkers are in the alpha
# package (alpha.statisticsbased), and maybe not in others. Lets
# figure out the actual checker name first.
special_return_value = next((
checker for checker, _ in checkers
if SpecialReturnValueCollector.checker_analyze in checker),
None)
unchecked_return_value = next((
checker for checker, _ in checkers
if ReturnValueCollector.checker_analyze in checker),
None)

if special_return_value and not _is_user_disabled_checker(
special_return_value,
cmdline_checkers):
handler.set_checker_enabled(special_return_value)

if unchecked_return_value and not _is_user_disabled_checker(
unchecked_return_value,
cmdline_checkers):
handler.set_checker_enabled(unchecked_return_value)

# Statistics collector checkers must be explicitly disabled as they
# trash the output. These checkers are executed in a preceding analysis
# phase.
handler.set_checker_enabled(
SpecialReturnValueCollector.checker_collect, False)

handler.set_checker_enabled(
ReturnValueCollector.checker_collect, False)

handler.checker_config = []

# TODO: This extra "isinstance" check is needed for
Expand Down
26 changes: 26 additions & 0 deletions analyzer/tests/unit/test_checker_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"""


from distutils import util
import os
import unittest
from argparse import Namespace

Expand Down Expand Up @@ -148,10 +150,15 @@ def f(checks, checkers):
'security.insecureAPI.bcmp',
'alpha.llvm.Conventions']

statisticsbased = [
'statisticsbased.SpecialReturnValue',
'statisticsbased.UncheckedReturnValue']

checkers = []
checkers.extend(map(add_description, security_profile_alpha))
checkers.extend(map(add_description, default_profile))
checkers.extend(map(add_description, cert_guideline))
checkers.extend(map(add_description, statisticsbased))

# "default" profile checkers are enabled explicitly. Others are in
# "default" state.
Expand Down Expand Up @@ -232,6 +239,25 @@ def f(checks, checkers):
self.assertTrue(all_with_status(CheckerState.enabled)
(cfg_handler.checks(), low_severity))

# Test if statisticsbased checkers are enabled by --stats flag
# by default.
stats_capable = bool(util.strtobool(
os.environ.get('CC_TEST_FORCE_STATS_CAPABLE', 'False')))

if stats_capable:
cfg_handler = ClangSA.construct_config_handler(
Namespace(stats_enabled=True))
cfg_handler.initialize_checkers(checkers, [])

enabled_checkers = (
checker for checker, (enabled, _)
in cfg_handler.checks().items()
if enabled == CheckerState.enabled)

for stat_checker in statisticsbased:
self.assertTrue(
any(stat_checker in c for c in enabled_checkers))


def create_analyzer_tidy(args=[]):
cfg_handler = ClangTidy.construct_config_handler(args)
Expand Down