Repository: ericsson/codechecker
Issue:  'aggressive-binary-operation-simplification' should be clang version dependent

  'aggressive-binary-operation-simplification option is only available since clang 8.
This option should not be passed to clang with earlier versions.


Changed files:
analyzer/codechecker_analyzer/analyzers/clangsa/version.py, analyzer/codechecker_analyzer/analyzers/clangsa/config_handler.py, analyzer/codechecker_analyzer/analyzers/clangsa/clang_options.py, analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py

diff --git a/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py b/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
index dfdcabf1..c442e4a2 100644
--- a/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
+++ b/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
@@ -113,29 +113,14 @@ class ClangSA(analyzer_base.SourceAnalyzer):
     @classmethod
     def get_analyzer_checkers(cls, cfg_handler, environ):
         """Return the list of the supported checkers."""
-        analyzer_binary = cfg_handler.analyzer_binary
-
-        try:
-            analyzer_version = subprocess.check_output(
-                [analyzer_binary, '--version'],
-                env=environ)
-
-        except subprocess.CalledProcessError as cerr:
-            LOG.error('Failed to get and parse clang version: %s',
-                      analyzer_binary)
-            LOG.error(cerr)
-            return []
-
-        version_parser = version.ClangVersionInfoParser()
-        version_info = version_parser.parse(analyzer_version)
-
-        command = [analyzer_binary, "-cc1"]
-
         checkers_list_args = clang_options.get_analyzer_checkers_cmd(
-            version_info,
+            cfg_handler.version_info,
             environ,
             cfg_handler.analyzer_plugins,
             alpha=True)
+
+        analyzer_binary = cfg_handler.analyzer_binary
+        command = [analyzer_binary, "-cc1"]
         command.extend(checkers_list_args)
 
         try:
@@ -200,12 +185,9 @@ class ClangSA(analyzer_base.SourceAnalyzer):
                                          '-analyzer-disable-checker=' +
                                          checker_name])
 
-            # Needed for the iterator checkers.
-            analyzer_cmd.extend(['-Xclang',
-                                 '-analyzer-config',
-                                 '-Xclang',
-                                 'aggressive-binary-operation-simplification'
-                                 '=true'])
+            # Enable aggressive-binary-operation-simplification option.
+            analyzer_cmd.extend(
+                clang_options.get_abos_options(config.version_info))
 
             # Enable the z3 solver backend.
             if config.enable_z3:
@@ -344,6 +326,7 @@ class ClangSA(analyzer_base.SourceAnalyzer):
             cls.ANALYZER_NAME)
         handler.compiler_resource_dir = \\
             host_check.get_resource_dir(handler.analyzer_binary, context)
+        handler.version_info = version.get(handler.analyzer_binary, environ)
 
         handler.report_hash = args.report_hash \\
             if 'report_hash' in args else None
diff --git a/analyzer/codechecker_analyzer/analyzers/clangsa/clang_options.py b/analyzer/codechecker_analyzer/analyzers/clangsa/clang_options.py
index 7ba61f1d..52a32413 100644
--- a/analyzer/codechecker_analyzer/analyzers/clangsa/clang_options.py
+++ b/analyzer/codechecker_analyzer/analyzers/clangsa/clang_options.py
@@ -94,3 +94,20 @@ def ctu_mapping(clang_version_info):
         "found in directory reported by Clang '%s'.",
         postfixed_tool_path, installed_dir)
     return None, None
+
+
+def get_abos_options(clang_version_info):
+    """ Get options to enable aggressive-binary-operation-simplification.
+
+    Returns list of options which enables
+    aggressive-binary-operation-simplification option (which is needed for the
+    iterator checker) if the Clang version is greater then 8.
+    Otherwise returns an empty list.
+    """
+    if clang_version_info and clang_version_info.major_version >= 8:
+        return ['-Xclang',
+                '-analyzer-config',
+                '-Xclang',
+                'aggressive-binary-operation-simplification=true']
+
+    return []
diff --git a/analyzer/codechecker_analyzer/analyzers/clangsa/config_handler.py b/analyzer/codechecker_analyzer/analyzers/clangsa/config_handler.py
index e13bcb69..4304967d 100644
--- a/analyzer/codechecker_analyzer/analyzers/clangsa/config_handler.py
+++ b/analyzer/codechecker_analyzer/analyzers/clangsa/config_handler.py
@@ -34,6 +34,7 @@ class ClangSAConfigHandler(config_handler.AnalyzerConfigHandler):
         self.enable_z3 = False
         self.enable_z3_refutation = False
         self.environ = environ
+        self.version_info = None
 
     def add_checker_config(self, config):
         """
diff --git a/analyzer/codechecker_analyzer/analyzers/clangsa/version.py b/analyzer/codechecker_analyzer/analyzers/clangsa/version.py
index 0ea28ba2..69ccc20d 100644
--- a/analyzer/codechecker_analyzer/analyzers/clangsa/version.py
+++ b/analyzer/codechecker_analyzer/analyzers/clangsa/version.py
@@ -10,6 +10,7 @@ from __future__ import division
 from __future__ import absolute_import
 
 import re
+import subprocess
 
 
 class ClangVersionInfo(object):
@@ -55,3 +56,12 @@ class ClangVersionInfoParser(object):
             version_match.group('minor_version'),
             version_match.group('patch_version'),
             installed_dir_match.group('installed_dir'))
+
+
+def get(clang_binary, env=None):
+    """Get and parse the version information from given clang binary."""
+    compiler_version = subprocess.check_output([clang_binary, '--version'],
+                                               env=env)
+    version_parser = ClangVersionInfoParser()
+    version_info = version_parser.parse(compiler_version)
+    return version_info