]> granicus.if.org Git - php/commitdiff
integrate clang analyzer
authorAnatol Belski <ab@php.net>
Sun, 28 Aug 2016 16:06:27 +0000 (18:06 +0200)
committerAnatol Belski <ab@php.net>
Sun, 28 Aug 2016 17:42:41 +0000 (19:42 +0200)
win32/build/config.w32
win32/build/confutils.js

index 58b1420b898c27702cd628c074735b11c443e7ad..73347e8529a1d98cb3ea5d997a1e0969d4aba402 100644 (file)
@@ -212,11 +212,27 @@ if (PHP_SECURITY_FLAGS == "yes") {
        ADD_FLAG("LDFLAGS", "/NXCOMPAT /DYNAMICBASE ");
 }
 
-/* XXX add and implement clang keyword for clang analyzer */
 ARG_WITH("analyzer", "Enable static analyzer. Pass vs for Visual Studio, pvs for PVS-Studio", "no");
 if (PHP_ANALYZER == "vs") {
        ADD_FLAG("CFLAGS", " /analyze ");
        ADD_FLAG("CFLAGS", " /wd6308 ");
+} else if (PHP_ANALYZER == "clang") {
+       var clang_cl = false;
+
+       if (FSO.FileExists(PROGRAM_FILES + "\\LLVM\\bin\\clang-cl.exe")) {
+               clang_cl = PROGRAM_FILES + "\\LLVM\\bin\\clang-cl.exe";
+       } else if (FSO.FileExists(PROGRAM_FILES + "\\LLVM\\bin\\clang-cl.exe")) {
+               clang_cl = PROGRAM_FILES + "\\LLVM\\bin\\clang-cl.exe";
+       }
+
+       if (!clang_cl) {
+               if (false == PATH_PROG('clang-cl', null, 'CLANG_CL')) {
+                       WARNING("Couldn't find clang binaries, static analyze was disabled");
+                       PHP_ANALYZER = "no";
+               }
+       } else {
+               DEFINE("CLANG_CL", clang_cl);
+       }
 } else if (PHP_ANALYZER == "pvs") {
        var pvs_studio = false;
 
index 038692911c749de5649f68a9e3a670bf29b8cb07..0f87b8ac92e716cd85df1c43439692a9666572e3 100644 (file)
@@ -1526,19 +1526,37 @@ function ADD_SOURCES(dir, file_list, target, obj_dir)
                        ADD_FLAG(bd_flags_name, "/Fd" + sub_build + d);
                }
 
+               if (PHP_ANALYZER == "clang") {
+                       var analyzer_base_args = X64 ? "-m64" : "-m32";
+                       
+                       analyzer_base_args += " --analyze";
+
+                       var vc_ver;
+                       if (VS_TOOLSET) {
+                               vc_ver = VCVERS;
+                       } else {
+                               vc_ver = probe_binary(PATH_PROG('cl', null));
+                       }
+
+                       analyzer_base_args += " -fms-compatibility -fms-compatibility-version=" + vc_ver + " -fms-extensions";
+               }
+
                if (PHP_MP_DISABLED) {
                        for (var j in srcs_by_dir[k]) {
                                src = file_list[srcs_by_dir[k][j]];
-                               if (PHP_ANALYZER == "pvs") {
-                                       MFO.WriteLine("\t@\"$(PVS_STUDIO)\" --cl-params $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " --source-file "  + dir + "\\" + src
-                                               + " --cfg PVS-Studio.conf --errors-off \"V122 V117 V111\" ");
-                               }
 
                                var _tmp = src.split("\\");
                                var filename = _tmp.pop();
                                obj = filename.replace(re, ".obj");
 
                                MFO.WriteLine("\t@$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " /Fo" + sub_build + d + obj);
+
+                               if ("clang" == PHP_ANALYZER) {
+                                       MFO.WriteLine("\t\"@$(CLANG_CL)\" " + analyzer_base_args + " $(" + flags + "_ANALYZER) $(CFLAGS_ANALYZER) $(" + bd_flags_name + "_ANALYZER) /c " + dir + "\\" + src); 
+                               }else if (PHP_ANALYZER == "pvs") {
+                                       MFO.WriteLine("\t@\"$(PVS_STUDIO)\" --cl-params $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " --source-file "  + dir + "\\" + src
+                                               + " --cfg PVS-Studio.conf --errors-off \"V122 V117 V111\" ");
+                               }
                        }
                } else {
                        /* TODO create a response file at least for the source files to work around the cmd line length limit. */
@@ -1548,6 +1566,10 @@ function ADD_SOURCES(dir, file_list, target, obj_dir)
                        }
 
                        MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) /Fo" + sub_build + d + " $(" + bd_flags_name + ") /c " + src_line);
+
+                       if ("clang" == PHP_ANALYZER) {
+                               MFO.WriteLine("\t\"$(CLANG_CL)\" " + analyzer_base_args + " $(" + flags + "_ANALYZER) $(CFLAGS_ANALYZER)  $(" + bd_flags_name + "_ANALYZER) /c " + src_line);
+                       }
                }
        }
 
@@ -1729,6 +1751,8 @@ function write_summary()
        }
        if (PHP_ANALYZER == "vs") {
                ar[5] = ['Static analyzer', 'Visual Studio'];
+       } else if (PHP_ANALYZER == "clang") {
+               ar[5] = ['Static analyzer', 'clang'];
        } else if (PHP_ANALYZER == "pvs") {
                ar[5] = ['Static analyzer', 'PVS-Studio'];
        } else {
@@ -2057,6 +2081,54 @@ function generate_phpize()
        CJ.Close();
 }
 
+function handle_analyzer_makefile_flags(fd, key, val)
+{
+       var relevant = false;
+
+       /* VS integrates /analyze with the bulid process,
+               no further action is required. */
+       if ("no" == PHP_ANALYZER || "vs" == PHP_ANALYZER) {
+               return;
+       }
+
+       if (key.match("CFLAGS")) {
+               var new_val = val;
+               var reg = /\$\(([^\)]+)\)/g;
+               while (r = reg.exec(val)) {
+                       var repl = "$(" + r[1] + "_ANALYZER)"
+                       new_val = new_val.replace(r[0], repl);
+               }
+               val = new_val;
+
+               if ("clang" == PHP_ANALYZER) {  
+                       val = val.replace(/\/FD /, "")
+                               .replace(/\/Fp.+? /, "")
+                               .replace(/\/Fo.+? /, "")
+                               .replace(/\/Fd.+? /, "")
+                               //.replace(/\/Fd.+?/, " ")
+                               .replace(/\/FR.+? /, "")
+                               .replace("/guard:cf ", "")
+                               .replace(/\/MP \d+ /, "")
+                               .replace(/\/MP /, "")
+                               .replace("/LD ", "");
+               }
+       
+               relevant = true;
+       } else if (key.match("BASE_INCLUDES")) {
+               relevant = true;
+       }
+
+       if (!relevant) {
+               return;
+       }
+
+       key += "_ANALYZER";
+       //WARNING("KEY: " + key + " VAL: " + val);
+
+       fd.WriteLine(key + "=" + val + " ");
+       fd.WriteBlankLines(1);
+}
+
 /* Generate the Makefile */
 function generate_makefile()
 {
@@ -2072,12 +2144,16 @@ function generate_makefile()
                // The trailing space is needed to prevent the trailing backslash
                // that is part of the build dir flags (CFLAGS_BD_XXX) from being
                // seen as a line continuation character
-               MF.WriteLine(keys[i] + "=" + 
-                       /* \s+\/ eliminates extra whitespace caused when using \ for string continuation,
-                               whereby \/ is the start of the next compiler switch */
-                       trim(configure_subst.Item(keys[i])).replace(/\s+\//gm, " /") + " "
-                       );
+
+               /* \s+\/ eliminates extra whitespace caused when using \ for string continuation,
+                       whereby \/ is the start of the next compiler switch */
+               var val = trim(configure_subst.Item(keys[i])).replace(/\s+\//gm, " /");
+               
+               MF.WriteLine(keys[i] + "=" + val + " ");
                MF.WriteBlankLines(1);
+
+               /* If static analyze is enabled, add analyzer specific stuff to the Makefile. */
+               handle_analyzer_makefile_flags(MF, keys[i], val);
        }
 
        MF.WriteBlankLines(1);