[analyzer][CrossTU][NFC] Generalize to external definitions instead of external functions

Summary: This is just changing naming and documentation to be general about external definitions that can be imported for cross translation unit analysis. There is at least a plan to add VarDecls: D46421

Reviewers: NoQ, xazax.hun, martong, a.sidorin, george.karpenkov, serge-sans-paille

Reviewed By: xazax.hun, martong

Subscribers: mgorny, whisperity, baloghadamsoftware, szepet, rnkovacs, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, cfe-commits

Differential Revision: https://reviews.llvm.org/D56441

llvm-svn: 350852
diff --git a/clang/tools/scan-build-py/README.md b/clang/tools/scan-build-py/README.md
index 720bde1..01e3454 100644
--- a/clang/tools/scan-build-py/README.md
+++ b/clang/tools/scan-build-py/README.md
@@ -53,7 +53,7 @@
     
     $ analyze-build --ctu
 
-For CTU analysis an additional (function-definition) collection-phase is required. 
+For CTU analysis an additional (external definition) collection-phase is required. 
 For debugging purposes, it is possible to separately execute the collection 
 and the analysis phase. By doing this, the intermediate files used for 
 the analysis are kept on the disk in `./ctu-dir`.
diff --git a/clang/tools/scan-build-py/libscanbuild/__init__.py b/clang/tools/scan-build-py/libscanbuild/__init__.py
index e7b7487..903207c 100644
--- a/clang/tools/scan-build-py/libscanbuild/__init__.py
+++ b/clang/tools/scan-build-py/libscanbuild/__init__.py
@@ -20,7 +20,7 @@
 Execution = collections.namedtuple('Execution', ['pid', 'cwd', 'cmd'])
 
 CtuConfig = collections.namedtuple('CtuConfig', ['collect', 'analyze', 'dir',
-                                                 'func_map_cmd'])
+                                                 'extdef_map_cmd'])
 
 
 def duplicate_check(method):
diff --git a/clang/tools/scan-build-py/libscanbuild/analyze.py b/clang/tools/scan-build-py/libscanbuild/analyze.py
index ec2ffbb..ab8ea62 100644
--- a/clang/tools/scan-build-py/libscanbuild/analyze.py
+++ b/clang/tools/scan-build-py/libscanbuild/analyze.py
@@ -42,8 +42,8 @@
 COMPILER_WRAPPER_CC = 'analyze-cc'
 COMPILER_WRAPPER_CXX = 'analyze-c++'
 
-CTU_FUNCTION_MAP_FILENAME = 'externalFnMap.txt'
-CTU_TEMP_FNMAP_FOLDER = 'tmpExternalFnMaps'
+CTU_EXTDEF_MAP_FILENAME = 'externalDefMap.txt'
+CTU_TEMP_DEFMAP_FOLDER = 'tmpExternalDefMaps'
 
 
 @command_entry_point
@@ -117,9 +117,9 @@
         CtuConfig(collect=args.ctu_phases.collect,
                   analyze=args.ctu_phases.analyze,
                   dir=args.ctu_dir,
-                  func_map_cmd=args.func_map_cmd)
+                  extdef_map_cmd=args.extdef_map_cmd)
         if hasattr(args, 'ctu_phases') and hasattr(args.ctu_phases, 'dir')
-        else CtuConfig(collect=False, analyze=False, dir='', func_map_cmd=''))
+        else CtuConfig(collect=False, analyze=False, dir='', extdef_map_cmd=''))
 
 
 def get_ctu_config_from_json(ctu_conf_json):
@@ -130,23 +130,24 @@
     return CtuConfig(collect=ctu_config[0],
                      analyze=ctu_config[1],
                      dir=ctu_config[2],
-                     func_map_cmd=ctu_config[3])
+                     extdef_map_cmd=ctu_config[3])
 
 
-def create_global_ctu_function_map(func_map_lines):
-    """ Takes iterator of individual function maps and creates a global map
-    keeping only unique names. We leave conflicting names out of CTU.
+def create_global_ctu_extdef_map(extdef_map_lines):
+    """ Takes iterator of individual external definition maps and creates a
+    global map keeping only unique names. We leave conflicting names out of
+    CTU.
 
-    :param func_map_lines: Contains the id of a function (mangled name) and
+    :param extdef_map_lines: Contains the id of a definition (mangled name) and
     the originating source (the corresponding AST file) name.
-    :type func_map_lines: Iterator of str.
+    :type extdef_map_lines: Iterator of str.
     :returns: Mangled name - AST file pairs.
     :rtype: List of (str, str) tuples.
     """
 
     mangled_to_asts = defaultdict(set)
 
-    for line in func_map_lines:
+    for line in extdef_map_lines:
         mangled_name, ast_file = line.strip().split(' ', 1)
         mangled_to_asts[mangled_name].add(ast_file)
 
@@ -159,20 +160,20 @@
     return mangled_ast_pairs
 
 
-def merge_ctu_func_maps(ctudir):
-    """ Merge individual function maps into a global one.
+def merge_ctu_extdef_maps(ctudir):
+    """ Merge individual external definition maps into a global one.
 
     As the collect phase runs parallel on multiple threads, all compilation
-    units are separately mapped into a temporary file in CTU_TEMP_FNMAP_FOLDER.
-    These function maps contain the mangled names of functions and the source
-    (AST generated from the source) which had them.
+    units are separately mapped into a temporary file in CTU_TEMP_DEFMAP_FOLDER.
+    These definition maps contain the mangled names and the source
+    (AST generated from the source) which had their definition.
     These files should be merged at the end into a global map file:
-    CTU_FUNCTION_MAP_FILENAME."""
+    CTU_EXTDEF_MAP_FILENAME."""
 
-    def generate_func_map_lines(fnmap_dir):
+    def generate_extdef_map_lines(extdefmap_dir):
         """ Iterate over all lines of input files in a determined order. """
 
-        files = glob.glob(os.path.join(fnmap_dir, '*'))
+        files = glob.glob(os.path.join(extdefmap_dir, '*'))
         files.sort()
         for filename in files:
             with open(filename, 'r') as in_file:
@@ -180,11 +181,11 @@
                     yield line
 
     def write_global_map(arch, mangled_ast_pairs):
-        """ Write (mangled function name, ast file) pairs into final file. """
+        """ Write (mangled name, ast file) pairs into final file. """
 
-        extern_fns_map_file = os.path.join(ctudir, arch,
-                                           CTU_FUNCTION_MAP_FILENAME)
-        with open(extern_fns_map_file, 'w') as out_file:
+        extern_defs_map_file = os.path.join(ctudir, arch,
+                                           CTU_EXTDEF_MAP_FILENAME)
+        with open(extern_defs_map_file, 'w') as out_file:
             for mangled_name, ast_file in mangled_ast_pairs:
                 out_file.write('%s %s\n' % (mangled_name, ast_file))
 
@@ -192,15 +193,15 @@
     for triple_path in triple_arches:
         if os.path.isdir(triple_path):
             triple_arch = os.path.basename(triple_path)
-            fnmap_dir = os.path.join(ctudir, triple_arch,
-                                     CTU_TEMP_FNMAP_FOLDER)
+            extdefmap_dir = os.path.join(ctudir, triple_arch,
+                                     CTU_TEMP_DEFMAP_FOLDER)
 
-            func_map_lines = generate_func_map_lines(fnmap_dir)
-            mangled_ast_pairs = create_global_ctu_function_map(func_map_lines)
+            extdef_map_lines = generate_extdef_map_lines(extdefmap_dir)
+            mangled_ast_pairs = create_global_ctu_extdef_map(extdef_map_lines)
             write_global_map(triple_arch, mangled_ast_pairs)
 
             # Remove all temporary files
-            shutil.rmtree(fnmap_dir, ignore_errors=True)
+            shutil.rmtree(extdefmap_dir, ignore_errors=True)
 
 
 def run_analyzer_parallel(args):
@@ -251,21 +252,21 @@
     # left so multiple analyze runs can use the same data gathered by a single
     # collection run.
     if ctu_config.collect and ctu_config.analyze:
-        # CTU strings are coming from args.ctu_dir and func_map_cmd,
+        # CTU strings are coming from args.ctu_dir and extdef_map_cmd,
         # so we can leave it empty
         args.ctu_phases = CtuConfig(collect=True, analyze=False,
-                                    dir='', func_map_cmd='')
+                                    dir='', extdef_map_cmd='')
         run_analyzer_parallel(args)
-        merge_ctu_func_maps(ctu_config.dir)
+        merge_ctu_extdef_maps(ctu_config.dir)
         args.ctu_phases = CtuConfig(collect=False, analyze=True,
-                                    dir='', func_map_cmd='')
+                                    dir='', extdef_map_cmd='')
         run_analyzer_parallel(args)
         shutil.rmtree(ctu_config.dir, ignore_errors=True)
     else:
         # Single runs (collect or analyze) are launched from here.
         run_analyzer_parallel(args)
         if ctu_config.collect:
-            merge_ctu_func_maps(ctu_config.dir)
+            merge_ctu_extdef_maps(ctu_config.dir)
 
 
 def setup_environment(args):
@@ -544,20 +545,20 @@
         return result
 
 
-def func_map_list_src_to_ast(func_src_list):
-    """ Turns textual function map list with source files into a
-    function map list with ast files. """
+def extdef_map_list_src_to_ast(extdef_src_list):
+    """ Turns textual external definition map list with source files into an
+    external definition map list with ast files. """
 
-    func_ast_list = []
-    for fn_src_txt in func_src_list:
-        mangled_name, path = fn_src_txt.split(" ", 1)
+    extdef_ast_list = []
+    for extdef_src_txt in extdef_src_list:
+        mangled_name, path = extdef_src_txt.split(" ", 1)
         # Normalize path on windows as well
         path = os.path.splitdrive(path)[1]
         # Make relative path out of absolute
         path = path[1:] if path[0] == os.sep else path
         ast_path = os.path.join("ast", path + ".ast")
-        func_ast_list.append(mangled_name + " " + ast_path)
-    return func_ast_list
+        extdef_ast_list.append(mangled_name + " " + ast_path)
+    return extdef_ast_list
 
 
 @require(['clang', 'directory', 'flags', 'direct_args', 'file', 'ctu'])
@@ -588,37 +589,38 @@
         logging.debug("Generating AST using '%s'", ast_command)
         run_command(ast_command, cwd=opts['directory'])
 
-    def map_functions(triple_arch):
-        """ Generate function map file for the current source. """
+    def map_extdefs(triple_arch):
+        """ Generate external definition map file for the current source. """
 
         args = opts['direct_args'] + opts['flags']
-        funcmap_command = [opts['ctu'].func_map_cmd]
-        funcmap_command.append(opts['file'])
-        funcmap_command.append('--')
-        funcmap_command.extend(args)
-        logging.debug("Generating function map using '%s'", funcmap_command)
-        func_src_list = run_command(funcmap_command, cwd=opts['directory'])
-        func_ast_list = func_map_list_src_to_ast(func_src_list)
-        extern_fns_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
-                                             CTU_TEMP_FNMAP_FOLDER)
-        if not os.path.isdir(extern_fns_map_folder):
+        extdefmap_command = [opts['ctu'].extdef_map_cmd]
+        extdefmap_command.append(opts['file'])
+        extdefmap_command.append('--')
+        extdefmap_command.extend(args)
+        logging.debug("Generating external definition map using '%s'",
+                      extdefmap_command)
+        extdef_src_list = run_command(extdefmap_command, cwd=opts['directory'])
+        extdef_ast_list = extdef_map_list_src_to_ast(extdef_src_list)
+        extern_defs_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
+                                             CTU_TEMP_DEFMAP_FOLDER)
+        if not os.path.isdir(extern_defs_map_folder):
             try:
-                os.makedirs(extern_fns_map_folder)
+                os.makedirs(extern_defs_map_folder)
             except OSError:
                 # In case an other process already created it.
                 pass
-        if func_ast_list:
+        if extdef_ast_list:
             with tempfile.NamedTemporaryFile(mode='w',
-                                             dir=extern_fns_map_folder,
+                                             dir=extern_defs_map_folder,
                                              delete=False) as out_file:
-                out_file.write("\n".join(func_ast_list) + "\n")
+                out_file.write("\n".join(extdef_ast_list) + "\n")
 
     cwd = opts['directory']
     cmd = [opts['clang'], '--analyze'] + opts['direct_args'] + opts['flags'] \
         + [opts['file']]
     triple_arch = get_triple_arch(cmd, cwd)
     generate_ast(triple_arch)
-    map_functions(triple_arch)
+    map_extdefs(triple_arch)
 
 
 @require(['ctu'])
diff --git a/clang/tools/scan-build-py/libscanbuild/arguments.py b/clang/tools/scan-build-py/libscanbuild/arguments.py
index eb8ea0d..58c56d2 100644
--- a/clang/tools/scan-build-py/libscanbuild/arguments.py
+++ b/clang/tools/scan-build-py/libscanbuild/arguments.py
@@ -135,10 +135,10 @@
         if args.ctu_phases.analyze and not args.ctu_phases.collect \
                 and not os.path.exists(args.ctu_dir):
             parser.error(message='missing CTU directory')
-        # Check CTU capability via checking clang-func-mapping
-        if not is_ctu_capable(args.func_map_cmd):
+        # Check CTU capability via checking clang-extdef-mapping
+        if not is_ctu_capable(args.extdef_map_cmd):
             parser.error(message="""This version of clang does not support CTU
-            functionality or clang-func-mapping command not found.""")
+            functionality or clang-extdef-mapping command not found.""")
 
 
 def create_intercept_parser():
@@ -366,7 +366,7 @@
             '--ctu',
             action='store_const',
             const=CtuConfig(collect=True, analyze=True,
-                            dir='', func_map_cmd=''),
+                            dir='', extdef_map_cmd=''),
             dest='ctu_phases',
             help="""Perform cross translation unit (ctu) analysis (both collect
             and analyze phases) using default <ctu-dir> for temporary output.
@@ -382,7 +382,7 @@
             '--ctu-collect-only',
             action='store_const',
             const=CtuConfig(collect=True, analyze=False,
-                            dir='', func_map_cmd=''),
+                            dir='', extdef_map_cmd=''),
             dest='ctu_phases',
             help="""Perform only the collect phase of ctu.
             Keep <ctu-dir> for further use.""")
@@ -390,20 +390,20 @@
             '--ctu-analyze-only',
             action='store_const',
             const=CtuConfig(collect=False, analyze=True,
-                            dir='', func_map_cmd=''),
+                            dir='', extdef_map_cmd=''),
             dest='ctu_phases',
             help="""Perform only the analyze phase of ctu. <ctu-dir> should be
             present and will not be removed after analysis.""")
         ctu.add_argument(
-            '--use-func-map-cmd',
+            '--use-extdef-map-cmd',
             metavar='<path>',
-            dest='func_map_cmd',
-            default='clang-func-mapping',
-            help="""'%(prog)s' uses the 'clang-func-mapping' executable
-            relative to itself for generating function maps for static
-            analysis. One can override this behavior with this option by using
-            the 'clang-func-mapping' packaged with Xcode (on OS X) or from the
-            PATH.""")
+            dest='extdef_map_cmd',
+            default='clang-extdef-mapping',
+            help="""'%(prog)s' uses the 'clang-extdef-mapping' executable
+            relative to itself for generating external definition maps for
+            static analysis. One can override this behavior with this option
+            by using the 'clang-extdef-mapping' packaged with Xcode (on OS X)
+            or from the PATH.""")
     return parser
 
 
diff --git a/clang/tools/scan-build-py/libscanbuild/clang.py b/clang/tools/scan-build-py/libscanbuild/clang.py
index ab42206..0cbfdb6 100644
--- a/clang/tools/scan-build-py/libscanbuild/clang.py
+++ b/clang/tools/scan-build-py/libscanbuild/clang.py
@@ -156,12 +156,12 @@
     return checkers
 
 
-def is_ctu_capable(func_map_cmd):
-    """ Detects if the current (or given) clang and function mapping
+def is_ctu_capable(extdef_map_cmd):
+    """ Detects if the current (or given) clang and external definition mapping
     executables are CTU compatible. """
 
     try:
-        run_command([func_map_cmd, '-version'])
+        run_command([extdef_map_cmd, '-version'])
     except (OSError, subprocess.CalledProcessError):
         return False
     return True
diff --git a/clang/tools/scan-build-py/tests/unit/test_analyze.py b/clang/tools/scan-build-py/tests/unit/test_analyze.py
index 9964a29..768a3b6 100644
--- a/clang/tools/scan-build-py/tests/unit/test_analyze.py
+++ b/clang/tools/scan-build-py/tests/unit/test_analyze.py
@@ -349,14 +349,14 @@
 class MergeCtuMapTest(unittest.TestCase):
 
     def test_no_map_gives_empty(self):
-        pairs = sut.create_global_ctu_function_map([])
+        pairs = sut.create_global_ctu_extdef_map([])
         self.assertFalse(pairs)
 
     def test_multiple_maps_merged(self):
         concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
                       'c:@F@fun2#I# ast/fun2.c.ast',
                       'c:@F@fun3#I# ast/fun3.c.ast']
-        pairs = sut.create_global_ctu_function_map(concat_map)
+        pairs = sut.create_global_ctu_extdef_map(concat_map)
         self.assertTrue(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
         self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
         self.assertTrue(('c:@F@fun3#I#', 'ast/fun3.c.ast') in pairs)
@@ -366,7 +366,7 @@
         concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
                       'c:@F@fun2#I# ast/fun2.c.ast',
                       'c:@F@fun1#I# ast/fun7.c.ast']
-        pairs = sut.create_global_ctu_function_map(concat_map)
+        pairs = sut.create_global_ctu_extdef_map(concat_map)
         self.assertFalse(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
         self.assertFalse(('c:@F@fun1#I#', 'ast/fun7.c.ast') in pairs)
         self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
@@ -376,28 +376,28 @@
         concat_map = ['c:@F@fun1#I# ast/fun1.c.ast',
                       'c:@F@fun2#I# ast/fun2.c.ast',
                       'c:@F@fun1#I# ast/fun1.c.ast']
-        pairs = sut.create_global_ctu_function_map(concat_map)
+        pairs = sut.create_global_ctu_extdef_map(concat_map)
         self.assertTrue(('c:@F@fun1#I#', 'ast/fun1.c.ast') in pairs)
         self.assertTrue(('c:@F@fun2#I#', 'ast/fun2.c.ast') in pairs)
         self.assertEqual(2, len(pairs))
 
     def test_space_handled_in_source(self):
         concat_map = ['c:@F@fun1#I# ast/f un.c.ast']
-        pairs = sut.create_global_ctu_function_map(concat_map)
+        pairs = sut.create_global_ctu_extdef_map(concat_map)
         self.assertTrue(('c:@F@fun1#I#', 'ast/f un.c.ast') in pairs)
         self.assertEqual(1, len(pairs))
 
 
-class FuncMapSrcToAstTest(unittest.TestCase):
+class ExtdefMapSrcToAstTest(unittest.TestCase):
 
     def test_empty_gives_empty(self):
-        fun_ast_lst = sut.func_map_list_src_to_ast([])
+        fun_ast_lst = sut.extdef_map_list_src_to_ast([])
         self.assertFalse(fun_ast_lst)
 
     def test_sources_to_asts(self):
         fun_src_lst = ['c:@F@f1#I# ' + os.path.join(os.sep + 'path', 'f1.c'),
                        'c:@F@f2#I# ' + os.path.join(os.sep + 'path', 'f2.c')]
-        fun_ast_lst = sut.func_map_list_src_to_ast(fun_src_lst)
+        fun_ast_lst = sut.extdef_map_list_src_to_ast(fun_src_lst)
         self.assertTrue('c:@F@f1#I# ' +
                         os.path.join('ast', 'path', 'f1.c.ast')
                         in fun_ast_lst)
@@ -408,7 +408,7 @@
 
     def test_spaces_handled(self):
         fun_src_lst = ['c:@F@f1#I# ' + os.path.join(os.sep + 'path', 'f 1.c')]
-        fun_ast_lst = sut.func_map_list_src_to_ast(fun_src_lst)
+        fun_ast_lst = sut.extdef_map_list_src_to_ast(fun_src_lst)
         self.assertTrue('c:@F@f1#I# ' +
                         os.path.join('ast', 'path', 'f 1.c.ast')
                         in fun_ast_lst)
diff --git a/clang/tools/scan-build-py/tests/unit/test_clang.py b/clang/tools/scan-build-py/tests/unit/test_clang.py
index 07ac4d9..7d625c6 100644
--- a/clang/tools/scan-build-py/tests/unit/test_clang.py
+++ b/clang/tools/scan-build-py/tests/unit/test_clang.py
@@ -96,7 +96,7 @@
 
 class ClangIsCtuCapableTest(unittest.TestCase):
     def test_ctu_not_found(self):
-        is_ctu = sut.is_ctu_capable('not-found-clang-func-mapping')
+        is_ctu = sut.is_ctu_capable('not-found-clang-extdef-mapping')
         self.assertFalse(is_ctu)