clang on windows support

1) Run python bin/fetch-clang-win
2) Set clang_win = "../bin/clang_win"
3) ???
4) Profit

Most changes here are to pass the right -mfoo flags to Clang
to enable advanced instruction sets, or fixed warning-as-errors.

BUG=skia:2679

Change-Id: Ieed145d35c209131c7c16fdd3ee11a3de4a1a921
Reviewed-on: https://skia-review.googlesource.com/28740
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/.gitignore b/.gitignore
index 0456db8..7705bdf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@
 bin/gn.exe
 bin/clang-format
 bin/clang-format.exe
+bin/clang_win
 
 vulkan-out
-gl-out
\ No newline at end of file
+gl-out
diff --git a/BUILD.gn b/BUILD.gn
index 5956f67..d837d1d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -250,7 +250,7 @@
 opts("sse2") {
   enabled = is_x86
   sources = skia_opts.sse2_sources
-  if (is_win) {
+  if (!is_clang && is_win) {
     defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE2" ]
   } else {
     cflags = [ "-msse2" ]
@@ -260,7 +260,7 @@
 opts("ssse3") {
   enabled = is_x86
   sources = skia_opts.ssse3_sources
-  if (is_win) {
+  if (!is_clang && is_win) {
     defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSSE3" ]
   } else {
     cflags = [ "-mssse3" ]
@@ -270,7 +270,7 @@
 opts("sse41") {
   enabled = is_x86
   sources = skia_opts.sse41_sources
-  if (is_win) {
+  if (!is_clang && is_win) {
     defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE41" ]
   } else {
     cflags = [ "-msse4.1" ]
@@ -280,7 +280,7 @@
 opts("sse42") {
   enabled = is_x86
   sources = skia_opts.sse42_sources
-  if (is_win) {
+  if (!is_clang && is_win) {
     defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE42" ]
   } else {
     cflags = [ "-msse4.2" ]
@@ -290,7 +290,7 @@
 opts("avx") {
   enabled = is_x86
   sources = skia_opts.avx_sources
-  if (is_win) {
+  if (!is_clang && is_win) {
     cflags = [ "/arch:AVX" ]
   } else {
     cflags = [ "-mavx" ]
diff --git a/bin/fetch-clang-win b/bin/fetch-clang-win
new file mode 100644
index 0000000..06ff07b
--- /dev/null
+++ b/bin/fetch-clang-win
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+VERSION = '308728-3'
+MD5     = '8bec8c34da5d256e27638383667489e5'
+
+import hashlib
+import os
+import shutil
+import tarfile
+import urllib2
+
+os.chdir(os.path.dirname(__file__))
+
+if (not os.path.exists('clang_win/md5.txt')
+        or open('clang_win/md5.txt').read().strip() != MD5):
+
+  # Clear out everything and start fresh.
+  shutil.rmtree('clang_win', ignore_errors=True)
+  os.mkdir('clang_win')
+  os.chdir('clang_win')
+
+  # Grab the current Clang package.
+  with open(VERSION + '.tgz', 'wb') as tgz:
+    url = 'https://commondatastorage.googleapis.com/chromium-browser-clang'
+    tgz.write(urllib2.urlopen(url + '/Win/clang-' + VERSION + '.tgz').read())
+
+  # Extract it.
+  tarfile.open(VERSION + '.tgz').extractall()
+
+  # Write out its hash to md5.txt so that next time is quicker.
+  h = hashlib.md5()
+  with open(VERSION + '.tgz', 'rb') as tgz:
+    h.update(tgz.read())
+  with open('md5.txt', 'w') as md5:
+    md5.write(h.hexdigest())
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 71475a8..ca9059d 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -13,16 +13,6 @@
   malloc = ""
 }
 
-is_clang = is_android || is_ios || is_mac || (cc == "clang" && cxx == "clang++")
-if (!is_clang && !is_win) {
-  is_clang = exec_script("is_clang.py",
-                         [
-                           cc,
-                           cxx,
-                         ],
-                         "value")
-}
-
 if (is_ios) {
   if (is_tvos) {
     sdk = "appletvos"
diff --git a/gn/BUILDCONFIG.gn b/gn/BUILDCONFIG.gn
index 43f66f8..ca91c1b 100644
--- a/gn/BUILDCONFIG.gn
+++ b/gn/BUILDCONFIG.gn
@@ -23,6 +23,7 @@
   cxx = "c++"
 
   msvc = 2015
+  clang_win = ""
 }
 declare_args() {
   is_debug = !is_official_build
@@ -68,6 +69,16 @@
   current_cpu = target_cpu
 }
 
+is_clang = is_android || is_ios || is_mac || (cc == "clang" && cxx == "clang++") || clang_win != ""
+if (!is_clang && !is_win) {
+  is_clang = exec_script("gn/is_clang.py",
+                         [
+                           cc,
+                           cxx,
+                         ],
+                         "value")
+}
+
 if (is_android) {
   ndk_host = ""
   ndk_target = ""
diff --git a/gn/toolchain/BUILD.gn b/gn/toolchain/BUILD.gn
index c5b1310..14a8a91 100644
--- a/gn/toolchain/BUILD.gn
+++ b/gn/toolchain/BUILD.gn
@@ -50,6 +50,13 @@
     }
   }
 
+  if (clang_win != "") {
+    cl = "$clang_win/bin/clang-cl.exe"
+  } else {
+    cl = "$bin/cl.exe"
+  }
+
+
   tool("asm") {
     _ml = "ml"
     if (target_cpu == "x64") {
@@ -68,7 +75,7 @@
     pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
 
     # Label names may have spaces so pdbname must be quoted.
-    command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
+    command = "$env_setup$cl /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
     depsformat = "msvc"
     outputs = [
       "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
@@ -83,7 +90,7 @@
     pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
 
     # Label names may have spaces so pdbname must be quoted.
-    command = "$env_setup$bin/cl.exe /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
+    command = "$env_setup$cl /nologo /showIncludes /FC @$rspfile /c {{source}} /Fo{{output}} /Fd\"$pdbname\""
     depsformat = "msvc"
     outputs = [
       "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h
index 8dcc18c..3a39f66 100644
--- a/include/core/SkPostConfig.h
+++ b/include/core/SkPostConfig.h
@@ -245,7 +245,7 @@
 //////////////////////////////////////////////////////////////////////
 
 #if !defined(SK_UNUSED)
-#  if defined(_MSC_VER)
+#  if !defined(__clang__) && defined(_MSC_VER)
 #    define SK_UNUSED __pragma(warning(suppress:4189))
 #  else
 #    define SK_UNUSED SK_ATTRIBUTE(unused)
diff --git a/samplecode/SampleBigGradient.cpp b/samplecode/SampleBigGradient.cpp
index b5b01c7..9d850c9 100644
--- a/samplecode/SampleBigGradient.cpp
+++ b/samplecode/SampleBigGradient.cpp
@@ -164,7 +164,8 @@
         HDC hdc = (HDC)fCanvas->accessTopRasterHandle();
 
         COLORREF cr = RGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));// SkEndian_Swap32(c) >> 8;
-        FillRect(hdc, &toRECT(r.round()), CreateSolidBrush(cr));
+        RECT rounded = toRECT(r.round());
+        FillRect(hdc, &rounded, CreateSolidBrush(cr));
 
         // Assuming GDI wrote zeros for alpha, this will or-in 0xFF for alpha
         SkPaint paint;
@@ -244,7 +245,8 @@
         xf.eDy = ctm[SkMatrix::kMTransY];
         SetWorldTransform(hdc, &xf);
 
-        HRGN hrgn = CreateRectRgnIndirect(&toRECT(clip_bounds));
+        RECT clip_bounds_RECT = toRECT(clip_bounds);
+        HRGN hrgn = CreateRectRgnIndirect(&clip_bounds_RECT);
         int result = SelectClipRgn(hdc, hrgn);
         SkASSERT(result != ERROR);
         result = DeleteObject(hrgn);
diff --git a/src/ports/SkImageEncoder_WIC.cpp b/src/ports/SkImageEncoder_WIC.cpp
index 1ae9257..dc51604 100644
--- a/src/ports/SkImageEncoder_WIC.cpp
+++ b/src/ports/SkImageEncoder_WIC.cpp
@@ -159,7 +159,7 @@
         PROPBAG2 name = { 0 };
         name.dwType = PROPBAG2_TYPE_DATA;
         name.vt = VT_R4;
-        name.pstrName = L"ImageQuality";
+        name.pstrName = const_cast<LPOLESTR>(L"ImageQuality");
 
         VARIANT value;
         VariantInit(&value);
diff --git a/src/utils/win/SkWGL_win.cpp b/src/utils/win/SkWGL_win.cpp
index d46123d..cce7a56 100644
--- a/src/utils/win/SkWGL_win.cpp
+++ b/src/utils/win/SkWGL_win.cpp
@@ -229,7 +229,7 @@
 }
 
 #define GET_PROC(NAME, SUFFIX) f##NAME = \
-                     (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
+                     (NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
 
 SkWGLExtensions::SkWGLExtensions()
     : fGetExtensionsString(nullptr)
diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp
index 8be15d1..4c5f151 100644
--- a/src/views/win/SkOSWindow_win.cpp
+++ b/src/views/win/SkOSWindow_win.cpp
@@ -243,58 +243,6 @@
     SetWindowTextA((HWND)fHWND, title);
 }
 
-enum {
-    SK_MacReturnKey     = 36,
-    SK_MacDeleteKey     = 51,
-    SK_MacEndKey        = 119,
-    SK_MacLeftKey       = 123,
-    SK_MacRightKey      = 124,
-    SK_MacDownKey       = 125,
-    SK_MacUpKey         = 126,
-
-    SK_Mac0Key          = 0x52,
-    SK_Mac1Key          = 0x53,
-    SK_Mac2Key          = 0x54,
-    SK_Mac3Key          = 0x55,
-    SK_Mac4Key          = 0x56,
-    SK_Mac5Key          = 0x57,
-    SK_Mac6Key          = 0x58,
-    SK_Mac7Key          = 0x59,
-    SK_Mac8Key          = 0x5b,
-    SK_Mac9Key          = 0x5c
-};
-
-static SkKey raw2key(uint32_t raw)
-{
-    static const struct {
-        uint32_t  fRaw;
-        SkKey   fKey;
-    } gKeys[] = {
-        { SK_MacUpKey,      kUp_SkKey       },
-        { SK_MacDownKey,    kDown_SkKey     },
-        { SK_MacLeftKey,    kLeft_SkKey     },
-        { SK_MacRightKey,   kRight_SkKey    },
-        { SK_MacReturnKey,  kOK_SkKey       },
-        { SK_MacDeleteKey,  kBack_SkKey     },
-        { SK_MacEndKey,     kEnd_SkKey      },
-        { SK_Mac0Key,       k0_SkKey        },
-        { SK_Mac1Key,       k1_SkKey        },
-        { SK_Mac2Key,       k2_SkKey        },
-        { SK_Mac3Key,       k3_SkKey        },
-        { SK_Mac4Key,       k4_SkKey        },
-        { SK_Mac5Key,       k5_SkKey        },
-        { SK_Mac6Key,       k6_SkKey        },
-        { SK_Mac7Key,       k7_SkKey        },
-        { SK_Mac8Key,       k8_SkKey        },
-        { SK_Mac9Key,       k9_SkKey        }
-    };
-
-    for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
-        if (gKeys[i].fRaw == raw)
-            return gKeys[i].fKey;
-    return kNONE_SkKey;
-}
-
 ///////////////////////////////////////////////////////////////////////////////////////
 
 void SkEvent::SignalNonEmptyQueue()
diff --git a/third_party/libwebp/BUILD.gn b/third_party/libwebp/BUILD.gn
index 7fec982..4ac2c5e 100644
--- a/third_party/libwebp/BUILD.gn
+++ b/third_party/libwebp/BUILD.gn
@@ -17,15 +17,7 @@
     ]
   }
 } else {
-  third_party("libwebp") {
-    public_include_dirs = [ "../externals/libwebp/src" ]
-
-    if (is_android) {
-      deps = [
-        "//third_party/cpu-features",
-      ]
-    }
-
+  config("libwebp_defines") {
     defines = [
       # WebP naturally decodes to RGB_565, and we work with BGR_565.
       # This makes WebP decode to BGR_565 when we ask for RGB_565.
@@ -33,7 +25,49 @@
       # TODO: swizzle ourself in SkWebpCodec instead of requiring this non-standard libwebp.
       "WEBP_SWAP_16BIT_CSP",
     ]
+  }
 
+  third_party("libwebp_sse41") {
+    public_include_dirs = [ "../externals/libwebp/src" ]
+    configs += [ ":libwebp_defines" ]
+    sources = [
+      "../externals/libwebp/src/dsp/alpha_processing_sse41.c",
+      "../externals/libwebp/src/dsp/dec_sse41.c",
+      "../externals/libwebp/src/dsp/enc_sse41.c",
+      "../externals/libwebp/src/dsp/lossless_enc_sse41.c",
+    ]
+    if ((current_cpu == "x86" || current_cpu == "x64") &&
+        (!is_win || is_clang)) {
+      cflags_c = ["-msse4.1"]
+    }
+  }
+
+  third_party("libwebp_avx2") {
+    public_include_dirs = [ "../externals/libwebp/src" ]
+    configs += [ ":libwebp_defines" ]
+    sources = [
+      "../externals/libwebp/src/dsp/enc_avx2.c",
+    ]
+    if ((current_cpu == "x86" || current_cpu == "x64") &&
+        (!is_win || is_clang)) {
+      cflags_c = ["-mavx2"]
+    }
+  }
+
+  third_party("libwebp") {
+    public_include_dirs = [ "../externals/libwebp/src" ]
+
+    deps = [
+      ":libwebp_sse41",
+      ":libwebp_avx2",
+    ]
+    if (is_android) {
+      deps += [
+        "//third_party/cpu-features",
+      ]
+    }
+
+    configs += [ ":libwebp_defines" ]
     sources = [
       "../externals/libwebp/src/dec/alpha_dec.c",
       "../externals/libwebp/src/dec/buffer_dec.c",
@@ -50,7 +84,6 @@
       "../externals/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c",
       "../externals/libwebp/src/dsp/alpha_processing_neon.c",
       "../externals/libwebp/src/dsp/alpha_processing_sse2.c",
-      "../externals/libwebp/src/dsp/alpha_processing_sse41.c",
       "../externals/libwebp/src/dsp/argb.c",
       "../externals/libwebp/src/dsp/argb_mips_dsp_r2.c",
       "../externals/libwebp/src/dsp/argb_sse2.c",
@@ -65,15 +98,12 @@
       "../externals/libwebp/src/dsp/dec_mips_dsp_r2.c",
       "../externals/libwebp/src/dsp/dec_neon.c",
       "../externals/libwebp/src/dsp/dec_sse2.c",
-      "../externals/libwebp/src/dsp/dec_sse41.c",
       "../externals/libwebp/src/dsp/enc.c",
-      "../externals/libwebp/src/dsp/enc_avx2.c",
       "../externals/libwebp/src/dsp/enc_mips32.c",
       "../externals/libwebp/src/dsp/enc_mips_dsp_r2.c",
       "../externals/libwebp/src/dsp/enc_msa.c",
       "../externals/libwebp/src/dsp/enc_neon.c",
       "../externals/libwebp/src/dsp/enc_sse2.c",
-      "../externals/libwebp/src/dsp/enc_sse41.c",
       "../externals/libwebp/src/dsp/filters.c",
       "../externals/libwebp/src/dsp/filters_mips_dsp_r2.c",
       "../externals/libwebp/src/dsp/filters_msa.c",
@@ -86,7 +116,6 @@
       "../externals/libwebp/src/dsp/lossless_enc_msa.c",
       "../externals/libwebp/src/dsp/lossless_enc_neon.c",
       "../externals/libwebp/src/dsp/lossless_enc_sse2.c",
-      "../externals/libwebp/src/dsp/lossless_enc_sse41.c",
       "../externals/libwebp/src/dsp/lossless_mips_dsp_r2.c",
       "../externals/libwebp/src/dsp/lossless_msa.c",
       "../externals/libwebp/src/dsp/lossless_neon.c",
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index 3f9bc5c..a1e4836 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -48,7 +48,7 @@
       "../externals/zlib/fill_window_sse.c",
       "../externals/zlib/x86.c",
     ]
-    if (!is_win) {
+    if (!is_win || is_clang) {
       cflags_c = [
         "-msse4.2",
         "-mpclmul",
diff --git a/tools/colorspaceinfo.cpp b/tools/colorspaceinfo.cpp
index c35e735..8250a03 100644
--- a/tools/colorspaceinfo.cpp
+++ b/tools/colorspaceinfo.cpp
@@ -476,7 +476,7 @@
 
     {
         SkColorSpaceTransferFn colorSpaceTransferFn;
-        SkMatrix44 toXYZD50;
+        SkMatrix44 toXYZD50(SkMatrix44::kIdentity_Constructor);
         if (colorSpace->isNumericalTransferFn(&colorSpaceTransferFn) &&
             colorSpace->toXYZD50(&toXYZD50)) {
             SkString description = SkICCGetColorProfileTag(colorSpaceTransferFn, toXYZD50);
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index 47f4aae..d957d53 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -369,7 +369,7 @@
     }
 }
 
-#if defined(_MSC_VER)
+#if !defined(__clang__) && defined(_MSC_VER)
     // MSVC takes ~2 minutes to compile this function with optimization.
     // We don't really care to wait that long for this function.
     #pragma optimize("", off)
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 6f01f2d..9e941f4 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -729,7 +729,7 @@
     if (ColorMode::kLegacy != fColorMode) {
         auto transferFn = (ColorMode::kColorManagedLinearF16 == fColorMode)
             ? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
-        SkMatrix44 toXYZ;
+        SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor);
         SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
         cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
     }