diff --git a/clang/tools/scan-build-py/libscanbuild/analyze.py b/clang/tools/scan-build-py/libscanbuild/analyze.py
--- a/clang/tools/scan-build-py/libscanbuild/analyze.py
+++ b/clang/tools/scan-build-py/libscanbuild/analyze.py
@@ -356,11 +356,14 @@
         yield name
     finally:
         if os.listdir(name):
-            if output_format != 'sarif':
+            if output_format not in ['sarif', 'sarif-html']: # FIXME:
                 # 'scan-view' currently does not support sarif format.
                 msg = "Run 'scan-view %s' to examine bug reports."
+            elif output_format == 'sarif-html':
+                msg = "Run 'scan-view %s' to examine bug reports or see " \
+                    "merged sarif results at %s/results-merged.sarif."
             else:
-                msg = "View result at %s/results-merged.sarif."
+                msg = "View merged sarif results at %s/results-merged.sarif."
             keep = True
         else:
             if keep:
@@ -438,7 +441,7 @@
           'direct_args',  # arguments from command line
           'force_debug',  # kill non debug macros
           'output_dir',  # where generated report files shall go
-          'output_format',  # it's 'plist', 'html', 'plist-html', 'plist-multi-file', or 'sarif'
+          'output_format',  # it's 'plist', 'html', 'plist-html', 'plist-multi-file', 'sarif', or 'sarif-html'
           'output_failures',  # generate crash reports or not
           'ctu'])  # ctu control options
 def run(opts):
@@ -542,7 +545,9 @@
                                               dir=opts['output_dir'])
             os.close(handle)
             return name
-        elif opts['output_format'] == 'sarif':
+        elif opts['output_format'] in {
+                'sarif',
+                'sarif-html'}:
             (handle, name) = tempfile.mkstemp(prefix='result-',
                                               suffix='.sarif',
                                               dir=opts['output_dir'])
diff --git a/clang/tools/scan-build-py/libscanbuild/arguments.py b/clang/tools/scan-build-py/libscanbuild/arguments.py
--- a/clang/tools/scan-build-py/libscanbuild/arguments.py
+++ b/clang/tools/scan-build-py/libscanbuild/arguments.py
@@ -252,6 +252,14 @@
         default='html',
         action='store_const',
         help="""Cause the results as a result.sarif file.""")
+    format_group.add_argument(
+        '--sarif-html',
+        '-sarif-html',
+        dest='output_format',
+        const='sarif-html',
+        default='html',
+        action='store_const',
+        help="""Cause the results as a result.sarif file and .html files.""")
 
     advanced = parser.add_argument_group('advanced options')
     advanced.add_argument(
diff --git a/clang/tools/scan-build-py/libscanbuild/report.py b/clang/tools/scan-build-py/libscanbuild/report.py
--- a/clang/tools/scan-build-py/libscanbuild/report.py
+++ b/clang/tools/scan-build-py/libscanbuild/report.py
@@ -26,8 +26,8 @@
 def document(args):
     """ Generates cover report and returns the number of bugs/crashes. """
 
-    html_reports_available = args.output_format in {'html', 'plist-html'}
-    sarif_reports_available = args.output_format in {'sarif'}
+    html_reports_available = args.output_format in {'html', 'plist-html', 'sarif-html'}
+    sarif_reports_available = args.output_format in {'sarif', 'sarif-html'}
 
     logging.debug('count crashes and bugs')
     crash_count = sum(1 for _ in read_crashes(args.output))
diff --git a/clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py b/clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py
--- a/clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py
+++ b/clang/tools/scan-build-py/tests/functional/cases/test_from_cdb.py
@@ -102,7 +102,11 @@
     def get_plist_count(directory):
         return len(glob.glob(os.path.join(directory, 'report-*.plist')))
 
-    def test_default_creates_html_report(self):
+    @staticmethod
+    def get_sarif_count(directory):
+        return len(glob.glob(os.path.join(directory, 'result-*.sarif')))
+
+    def test_default_only_creates_html_report(self):
         with libear.TemporaryDirectory() as tmpdir:
             cdb = prepare_cdb('regular', tmpdir)
             exit_code, reportdir = run_analyzer(tmpdir, cdb, [])
@@ -110,8 +114,9 @@
                 os.path.exists(os.path.join(reportdir, 'index.html')))
             self.assertEqual(self.get_html_count(reportdir), 2)
             self.assertEqual(self.get_plist_count(reportdir), 0)
+            self.assertEqual(self.get_sarif_count(reportdir), 0)
 
-    def test_plist_and_html_creates_html_report(self):
+    def test_plist_and_html_creates_html_and_plist_reports(self):
         with libear.TemporaryDirectory() as tmpdir:
             cdb = prepare_cdb('regular', tmpdir)
             exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist-html'])
@@ -119,8 +124,9 @@
                 os.path.exists(os.path.join(reportdir, 'index.html')))
             self.assertEqual(self.get_html_count(reportdir), 2)
             self.assertEqual(self.get_plist_count(reportdir), 5)
+            self.assertEqual(self.get_sarif_count(reportdir), 0)
 
-    def test_plist_does_not_creates_html_report(self):
+    def test_plist_only_creates_plist_report(self):
         with libear.TemporaryDirectory() as tmpdir:
             cdb = prepare_cdb('regular', tmpdir)
             exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--plist'])
@@ -128,6 +134,31 @@
                 os.path.exists(os.path.join(reportdir, 'index.html')))
             self.assertEqual(self.get_html_count(reportdir), 0)
             self.assertEqual(self.get_plist_count(reportdir), 5)
+            self.assertEqual(self.get_sarif_count(reportdir), 0)
+
+    def test_sarif_only_creates_sarif_result(self):
+        with libear.TemporaryDirectory() as tmpdir:
+            cdb = prepare_cdb('regular', tmpdir)
+            exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--sarif'])
+            self.assertFalse(
+                os.path.exists(os.path.join(reportdir, 'index.html')))
+            self.assertTrue(
+                os.path.exists(os.path.join(reportdir, 'results-merged.sarif')))
+            self.assertEqual(self.get_html_count(reportdir), 0)
+            self.assertEqual(self.get_plist_count(reportdir), 0)
+            self.assertEqual(self.get_sarif_count(reportdir), 5)
+
+    def test_sarif_and_html_creates_sarif_and_html_reports(self):
+        with libear.TemporaryDirectory() as tmpdir:
+            cdb = prepare_cdb('regular', tmpdir)
+            exit_code, reportdir = run_analyzer(tmpdir, cdb, ['--sarif-html'])
+            self.assertTrue(
+                os.path.exists(os.path.join(reportdir, 'index.html')))
+            self.assertTrue(
+                os.path.exists(os.path.join(reportdir, 'results-merged.sarif')))
+            self.assertEqual(self.get_html_count(reportdir), 2)
+            self.assertEqual(self.get_plist_count(reportdir), 0)
+            self.assertEqual(self.get_sarif_count(reportdir), 5)
 
 
 class FailureReportTest(unittest.TestCase):