Bug 1540357 - Force -Werror for and fix implicit int truncation in dom/canvas. r=lsalzman
authorJeff Gilbert <jgilbert@mozilla.com>
Tue, 02 Apr 2019 17:00:41 +0000
changeset 526436 08d7c5e08995786915ff90c15c85139401e78fcc
parent 526435 c6c69b6aa0fd3f07fcc9667baa9384b32484e0e2
child 526437 89552599db42520b12be078b9db8f848cce87a36
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1540357
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1540357 - Force -Werror for and fix implicit int truncation in dom/canvas. r=lsalzman Differential Revision: https://phabricator.services.mozilla.com/D25495
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasRenderingContext2D.h
dom/canvas/ImageBitmapColorUtils.cpp
dom/canvas/ImageBitmapUtils.cpp
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContextFramebufferOperations.cpp
dom/canvas/WebGLContextVertices.cpp
dom/canvas/WebGLTexelConversions.h
dom/canvas/WebGLTexture.cpp
dom/canvas/WebGLTexture.h
dom/canvas/WebGLTextureUpload.cpp
dom/canvas/WebGLTypes.h
dom/canvas/moz.build
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -887,33 +887,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_B
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasRenderingContext2D)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-CanvasRenderingContext2D::ContextState::ContextState()
-    : textAlign(TextAlign::START),
-      textBaseline(TextBaseline::ALPHABETIC),
-      shadowColor(0),
-      lineWidth(1.0f),
-      miterLimit(10.0f),
-      globalAlpha(1.0f),
-      shadowBlur(0.0),
-      dashOffset(0.0f),
-      op(mozilla::gfx::CompositionOp::OP_OVER),
-      fillRule(mozilla::gfx::FillRule::FILL_WINDING),
-      lineCap(mozilla::gfx::CapStyle::BUTT),
-      lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
-      filterString(u"none"),
-      filterSourceGraphicTainted(false),
-      imageSmoothingEnabled(true),
-      fontExplicitLanguage(false) {}
+CanvasRenderingContext2D::ContextState::ContextState() =  default;
 
 CanvasRenderingContext2D::ContextState::ContextState(const ContextState& aOther)
     : fontGroup(aOther.fontGroup),
       fontLanguage(aOther.fontLanguage),
       fontFont(aOther.fontFont),
       gradientStyles(aOther.gradientStyles),
       patternStyles(aOther.patternStyles),
       colorStyles(aOther.colorStyles),
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -940,36 +940,37 @@ class CanvasRenderingContext2D final : p
     RefPtr<nsAtom> fontLanguage;
     nsFont fontFont;
 
     EnumeratedArray<Style, Style::MAX, RefPtr<CanvasGradient>> gradientStyles;
     EnumeratedArray<Style, Style::MAX, RefPtr<CanvasPattern>> patternStyles;
     EnumeratedArray<Style, Style::MAX, nscolor> colorStyles;
 
     nsString font;
-    TextAlign textAlign;
-    TextBaseline textBaseline;
+    TextAlign textAlign = TextAlign::START;
+    TextBaseline textBaseline = TextBaseline::ALPHABETIC;
 
-    nscolor shadowColor;
+    nscolor shadowColor = 0;
 
     mozilla::gfx::Matrix transform;
     mozilla::gfx::Point shadowOffset;
-    mozilla::gfx::Float lineWidth;
-    mozilla::gfx::Float miterLimit;
-    mozilla::gfx::Float globalAlpha;
-    mozilla::gfx::Float shadowBlur;
-    nsTArray<mozilla::gfx::Float> dash;
-    mozilla::gfx::Float dashOffset;
+    mozilla::gfx::Float lineWidth = 1.0f;
+    mozilla::gfx::Float miterLimit = 10.0f;
+    mozilla::gfx::Float globalAlpha = 1.0f;
+    mozilla::gfx::Float shadowBlur = 0.0f;
 
-    mozilla::gfx::CompositionOp op;
-    mozilla::gfx::FillRule fillRule;
-    mozilla::gfx::CapStyle lineCap;
-    mozilla::gfx::JoinStyle lineJoin;
+    nsTArray<mozilla::gfx::Float> dash;
+    mozilla::gfx::Float dashOffset = 0.0f;
 
-    nsString filterString;
+    mozilla::gfx::CompositionOp op = mozilla::gfx::CompositionOp::OP_OVER;
+    mozilla::gfx::FillRule fillRule = mozilla::gfx::FillRule::FILL_WINDING;
+    mozilla::gfx::CapStyle lineCap = mozilla::gfx::CapStyle::BUTT;
+    mozilla::gfx::JoinStyle lineJoin = mozilla::gfx::JoinStyle::MITER_OR_BEVEL;
+
+    nsString filterString = nsString(u"none");
     nsTArray<nsStyleFilter> filterChain;
     // RAII object that we obtain when we start to observer SVG filter elements
     // for rendering changes.  When released we stop observing the SVG elements.
     nsCOMPtr<nsISupports> autoSVGFiltersObserver;
     mozilla::gfx::FilterDescription filter;
     nsTArray<RefPtr<mozilla::gfx::SourceSurface>> filterAdditionalImages;
 
     // This keeps track of whether the canvas was "tainted" or not when
@@ -978,20 +979,20 @@ class CanvasRenderingContext2D final : p
     // This is to stop bad actors from reading back data they shouldn't have
     // access to.
     //
     // This also limits what filters we can apply to the context; in particular
     // feDisplacementMap is restricted.
     //
     // We keep track of this to ensure that if this gets out of sync with the
     // tainted state of the canvas itself, we update our filters accordingly.
-    bool filterSourceGraphicTainted;
+    bool filterSourceGraphicTainted = false;
 
-    bool imageSmoothingEnabled;
-    bool fontExplicitLanguage;
+    bool imageSmoothingEnabled = true;
+    bool fontExplicitLanguage = false;
   };
 
   AutoTArray<ContextState, 3> mStyleStack;
 
   inline ContextState& CurrentState() {
     return mStyleStack[mStyleStack.Length() - 1];
   }
 
--- a/dom/canvas/ImageBitmapColorUtils.cpp
+++ b/dom/canvas/ImageBitmapColorUtils.cpp
@@ -14,19 +14,19 @@ namespace dom {
  * Utility function form libyuv source files.
  */
 static __inline int32_t clamp0(int32_t v) { return ((-(v) >> 31) & (v)); }
 
 static __inline int32_t clamp255(int32_t v) {
   return (((255 - (v)) >> 31) | (v)) & 255;
 }
 
-static __inline uint32_t Clamp(int32_t val) {
-  int v = clamp0(val);
-  return (uint32_t)(clamp255(v));
+static __inline uint8_t Clamp(int32_t val) {
+  const auto v = clamp0(val);
+  return uint8_t(clamp255(v));
 }
 
 #define YG 74 /* (int8_t)(1.164 * 64 + 0.5) */
 
 #define UB 127 /* min(63,(int8_t)(2.018 * 64)) */
 #define UG -25 /* (int8_t)(-0.391 * 64 - 0.5) */
 #define UR 0
 
@@ -42,26 +42,26 @@ static __inline uint32_t Clamp(int32_t v
 static __inline void YuvPixel(uint8_t y, uint8_t u, uint8_t v, uint8_t* b,
                               uint8_t* g, uint8_t* r) {
   int32_t y1 = ((int32_t)(y)-16) * YG;
   *b = Clamp((int32_t)((u * UB + v * VB) - (BB) + y1) >> 6);
   *g = Clamp((int32_t)((u * UG + v * VG) - (BG) + y1) >> 6);
   *r = Clamp((int32_t)((u * UR + v * VR) - (BR) + y1) >> 6);
 }
 
-static __inline int RGBToY(uint8_t r, uint8_t g, uint8_t b) {
-  return (66 * r + 129 * g + 25 * b + 0x1080) >> 8;
+static __inline uint8_t RGBToY(uint8_t r, uint8_t g, uint8_t b) {
+  return uint8_t((66 * r + 129 * g + 25 * b + 0x1080) >> 8);
 }
 
-static __inline int RGBToU(uint8_t r, uint8_t g, uint8_t b) {
-  return (112 * b - 74 * g - 38 * r + 0x8080) >> 8;
+static __inline uint8_t RGBToU(uint8_t r, uint8_t g, uint8_t b) {
+  return uint8_t((112 * b - 74 * g - 38 * r + 0x8080) >> 8);
 }
 
-static __inline int RGBToV(uint8_t r, uint8_t g, uint8_t b) {
-  return (112 * r - 94 * g - 18 * b + 0x8080) >> 8;
+static __inline uint8_t RGBToV(uint8_t r, uint8_t g, uint8_t b) {
+  return uint8_t((112 * r - 94 * g - 18 * b + 0x8080) >> 8);
 }
 
 /*
  * Generic functions.
  */
 template <int aSrcRIndex, int aSrcGIndex, int aSrcBIndex, int aDstRIndex,
           int aDstGIndex, int aDstBIndex, int aDstAIndex>
 static int RGBFamilyToRGBAFamily(const uint8_t* aSrcBuffer, int aSrcStride,
--- a/dom/canvas/ImageBitmapUtils.cpp
+++ b/dom/canvas/ImageBitmapUtils.cpp
@@ -186,17 +186,17 @@ class Utils {
   // Check whether or not the current ImageBitmapFormat can be converted from
   // the given ImageBitmapFormat.
   virtual bool CanConvertFrom(ImageBitmapFormat aSrcFormat) = 0;
 
   // Get the number of channels.
   uint8_t GetChannelCount() const { return mChannels; }
 
  protected:
-  Utils(uint32_t aChannels, ChannelPixelLayoutDataType aDataType)
+  Utils(uint8_t aChannels, ChannelPixelLayoutDataType aDataType)
       : mChannels(aChannels),
         mBytesPerPixelValue(GetBytesPerPixelValue(aDataType)),
         mDataType(aDataType) {}
 
   virtual ~Utils() {}
 
   const uint8_t mChannels;
   const int mBytesPerPixelValue;
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -123,17 +123,17 @@ WebGLContext::WebGLContext()
       mDataAllocGLCallCount(0),
       mBypassShaderValidation(false),
       mEmptyTFO(0),
       mContextLossHandler(this),
       mNeedsFakeNoAlpha(false),
       mNeedsFakeNoDepth(false),
       mNeedsFakeNoStencil(false),
       mAllowFBInvalidation(gfxPrefs::WebGLFBInvalidation()),
-      mMsaaSamples(gfxPrefs::WebGLMsaaSamples()) {
+      mMsaaSamples((uint8_t)gfxPrefs::WebGLMsaaSamples()) {
   mGeneration = 0;
   mInvalidated = false;
   mCapturedFrameInvalidated = false;
   mShouldPresent = true;
   mResetLayer = true;
   mOptionsFrozen = false;
   mDisableExtensions = false;
   mIsMesa = false;
--- a/dom/canvas/WebGLContextFramebufferOperations.cpp
+++ b/dom/canvas/WebGLContextFramebufferOperations.cpp
@@ -107,18 +107,18 @@ void WebGLContext::ClearStencil(GLint v)
   gl->fClearStencil(v);
 }
 
 void WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b,
                              WebGLboolean a) {
   const FuncScope funcScope(*this, "colorMask");
   if (IsContextLost()) return;
 
-  mColorWriteMask = uint8_t(bool(r)) << 0 | uint8_t(bool(g)) << 1 |
-                    uint8_t(bool(b)) << 2 | uint8_t(bool(a)) << 3;
+  mColorWriteMask = uint8_t(bool(r) << 0) | uint8_t(bool(g) << 1) |
+                    uint8_t(bool(b) << 2) | uint8_t(bool(a) << 3);
 }
 
 void WebGLContext::DepthMask(WebGLboolean b) {
   const FuncScope funcScope(*this, "depthMask");
   if (IsContextLost()) return;
 
   mDepthWriteMask = b;
   gl->fDepthMask(b);
--- a/dom/canvas/WebGLContextVertices.cpp
+++ b/dom/canvas/WebGLContextVertices.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
 
 #include "GLContext.h"
+#include "mozilla/Casting.h"
 #include "mozilla/CheckedInt.h"
 #include "WebGLBuffer.h"
 #include "WebGLFramebuffer.h"
 #include "WebGLProgram.h"
 #include "WebGLRenderbuffer.h"
 #include "WebGLShader.h"
 #include "WebGLTexture.h"
 #include "WebGLVertexArray.h"
@@ -396,17 +397,17 @@ void WebGLContext::VertexAttribAnyPointe
     gl->fVertexAttribIPointer(index, size, type, stride,
                               reinterpret_cast<void*>(byteOffset));
   } else {
     gl->fVertexAttribPointer(index, size, type, normalized, stride,
                              reinterpret_cast<void*>(byteOffset));
   }
 
   WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
-  vd.VertexAttribPointer(isFuncInt, buffer, size, type, normalized, stride,
+  vd.VertexAttribPointer(isFuncInt, buffer, AutoAssertCast(size), type, normalized, stride,
                          byteOffset);
   mBoundVertexArray->InvalidateCaches();
 }
 
 ////////////////////////////////////////
 
 void WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor) {
   const FuncScope funcScope(*this, "vertexAttribDivisor");
--- a/dom/canvas/WebGLTexelConversions.h
+++ b/dom/canvas/WebGLTexelConversions.h
@@ -516,19 +516,19 @@ MOZ_ALWAYS_INLINE void unpack<WebGLTexel
 // 3-channel formats
 template <>
 MOZ_ALWAYS_INLINE void unpack<WebGLTexelFormat::RGB565, uint16_t, uint8_t>(
     const uint16_t* __restrict src, uint8_t* __restrict dst) {
   uint16_t packedValue = src[0];
   uint8_t r = (packedValue >> 11) & 0x1F;
   uint8_t g = (packedValue >> 5) & 0x3F;
   uint8_t b = packedValue & 0x1F;
-  dst[0] = (r << 3) | (r & 0x7);
-  dst[1] = (g << 2) | (g & 0x3);
-  dst[2] = (b << 3) | (b & 0x7);
+  dst[0] = uint8_t(r << 3) | (r & 0x7);
+  dst[1] = uint8_t(g << 2) | (g & 0x3);
+  dst[2] = uint8_t(b << 3) | (b & 0x7);
   dst[3] = 0xFF;
 }
 
 template <>
 MOZ_ALWAYS_INLINE void unpack<WebGLTexelFormat::RGB8, uint8_t, uint8_t>(
     const uint8_t* __restrict src, uint8_t* __restrict dst) {
   dst[0] = src[0];
   dst[1] = src[1];
@@ -559,32 +559,32 @@ MOZ_ALWAYS_INLINE void unpack<WebGLTexel
 template <>
 MOZ_ALWAYS_INLINE void unpack<WebGLTexelFormat::RGBA4444, uint16_t, uint8_t>(
     const uint16_t* __restrict src, uint8_t* __restrict dst) {
   uint16_t packedValue = src[0];
   uint8_t r = (packedValue >> 12) & 0x0F;
   uint8_t g = (packedValue >> 8) & 0x0F;
   uint8_t b = (packedValue >> 4) & 0x0F;
   uint8_t a = packedValue & 0x0F;
-  dst[0] = (r << 4) | r;
-  dst[1] = (g << 4) | g;
-  dst[2] = (b << 4) | b;
-  dst[3] = (a << 4) | a;
+  dst[0] = uint8_t(r << 4) | r;
+  dst[1] = uint8_t(g << 4) | g;
+  dst[2] = uint8_t(b << 4) | b;
+  dst[3] = uint8_t(a << 4) | a;
 }
 
 template <>
 MOZ_ALWAYS_INLINE void unpack<WebGLTexelFormat::RGBA5551, uint16_t, uint8_t>(
     const uint16_t* __restrict src, uint8_t* __restrict dst) {
   uint16_t packedValue = src[0];
   uint8_t r = (packedValue >> 11) & 0x1F;
   uint8_t g = (packedValue >> 6) & 0x1F;
   uint8_t b = (packedValue >> 1) & 0x1F;
-  dst[0] = (r << 3) | (r & 0x7);
-  dst[1] = (g << 3) | (g & 0x7);
-  dst[2] = (b << 3) | (b & 0x7);
+  dst[0] = uint8_t(r << 3) | (r & 0x7);
+  dst[1] = uint8_t(g << 3) | (g & 0x7);
+  dst[2] = uint8_t(b << 3) | (b & 0x7);
   dst[3] = (packedValue & 0x1) ? 0xFF : 0;
 }
 
 template <>
 MOZ_ALWAYS_INLINE void unpack<WebGLTexelFormat::RGBA8, uint8_t, uint8_t>(
     const uint8_t* __restrict src, uint8_t* __restrict dst) {
   dst[0] = src[0];
   dst[1] = src[1];
@@ -956,43 +956,43 @@ pack<WebGLTexelFormat::RG32F, WebGLTexel
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // 3-channel formats
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::None, uint8_t,
      uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) {
-  *dst = (((src[0] & 0xF8) << 8) | ((src[1] & 0xFC) << 3) |
+  *dst = uint16_t(((src[0] & 0xF8) << 8) | ((src[1] & 0xFC) << 3) |
           ((src[2] & 0xF8) >> 3));
 }
 
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Premultiply,
      uint8_t, uint16_t>(const uint8_t* __restrict src,
                         uint16_t* __restrict dst) {
   float scaleFactor = src[3] / 255.0f;
   uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
   uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
   uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
-  *dst = (((srcR & 0xF8) << 8) | ((srcG & 0xFC) << 3) | ((srcB & 0xF8) >> 3));
+  *dst = uint16_t(((srcR & 0xF8) << 8) | ((srcG & 0xFC) << 3) | ((srcB & 0xF8) >> 3));
 }
 
 // FIXME: this routine is lossy and must be removed.
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Unpremultiply,
      uint8_t, uint16_t>(const uint8_t* __restrict src,
                         uint16_t* __restrict dst) {
   float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
   uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
   uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
   uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
-  *dst = (((srcR & 0xF8) << 8) | ((srcG & 0xFC) << 3) | ((srcB & 0xF8) >> 3));
+  *dst = uint16_t(((srcR & 0xF8) << 8) | ((srcG & 0xFC) << 3) | ((srcB & 0xF8) >> 3));
 }
 
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::None, uint8_t,
      uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) {
   dst[0] = src[0];
   dst[1] = src[1];
@@ -1116,79 +1116,79 @@ pack<WebGLTexelFormat::RGB32F, WebGLTexe
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // 4-channel formats
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::None, uint8_t,
      uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) {
-  *dst = (((src[0] & 0xF0) << 8) | ((src[1] & 0xF0) << 4) | (src[2] & 0xF0) |
+  *dst = uint16_t(((src[0] & 0xF0) << 8) | ((src[1] & 0xF0) << 4) | (src[2] & 0xF0) |
           (src[3] >> 4));
 }
 
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Premultiply,
      uint8_t, uint16_t>(const uint8_t* __restrict src,
                         uint16_t* __restrict dst) {
   float scaleFactor = src[3] / 255.0f;
   uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
   uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
   uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
-  *dst = (((srcR & 0xF0) << 8) | ((srcG & 0xF0) << 4) | (srcB & 0xF0) |
+  *dst = uint16_t(((srcR & 0xF0) << 8) | ((srcG & 0xF0) << 4) | (srcB & 0xF0) |
           (src[3] >> 4));
 }
 
 // FIXME: this routine is lossy and must be removed.
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Unpremultiply,
      uint8_t, uint16_t>(const uint8_t* __restrict src,
                         uint16_t* __restrict dst) {
   float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
   uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
   uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
   uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
-  *dst = (((srcR & 0xF0) << 8) | ((srcG & 0xF0) << 4) | (srcB & 0xF0) |
+  *dst = uint16_t(((srcR & 0xF0) << 8) | ((srcG & 0xF0) << 4) | (srcB & 0xF0) |
           (src[3] >> 4));
 }
 
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::None, uint8_t,
      uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst) {
-  *dst = (((src[0] & 0xF8) << 8) | ((src[1] & 0xF8) << 3) |
+  *dst = uint16_t(((src[0] & 0xF8) << 8) | ((src[1] & 0xF8) << 3) |
           ((src[2] & 0xF8) >> 2) | (src[3] >> 7));
 }
 
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Premultiply,
      uint8_t, uint16_t>(const uint8_t* __restrict src,
                         uint16_t* __restrict dst) {
   float scaleFactor = src[3] / 255.0f;
   uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
   uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
   uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
-  *dst = (((srcR & 0xF8) << 8) | ((srcG & 0xF8) << 3) | ((srcB & 0xF8) >> 2) |
+  *dst = uint16_t(((srcR & 0xF8) << 8) | ((srcG & 0xF8) << 3) | ((srcB & 0xF8) >> 2) |
           (src[3] >> 7));
 }
 
 // FIXME: this routine is lossy and must be removed.
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Unpremultiply,
      uint8_t, uint16_t>(const uint8_t* __restrict src,
                         uint16_t* __restrict dst) {
   float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
   uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
   uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
   uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
-  *dst = (((srcR & 0xF8) << 8) | ((srcG & 0xF8) << 3) | ((srcB & 0xF8) >> 2) |
+  *dst = uint16_t(((srcR & 0xF8) << 8) | ((srcG & 0xF8) << 3) | ((srcB & 0xF8) >> 2) |
           (src[3] >> 7));
 }
 
 template <>
 MOZ_ALWAYS_INLINE void
 pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::None, uint8_t,
      uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst) {
   dst[0] = src[0];
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLTexture.h"
 
 #include <algorithm>
 #include "GLContext.h"
+#include "mozilla/Casting.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/Unused.h"
 #include "ScopedGLHelpers.h"
 #include "WebGLContext.h"
 #include "WebGLContextUtils.h"
@@ -255,17 +256,17 @@ Maybe<const WebGLTexture::CompletenessIn
   if (skipMips) return ret;
 
   if (!IsMipAndCubeComplete(maxLevel, ensureInit, &initFailed)) {
     if (initFailed) return {};
 
     ret->incompleteReason = "Bad mipmap dimension or format.";
     return ret;
   }
-  ret->levels = maxLevel - mBaseMipmapLevel + 1;
+  ret->levels = AutoAssertCast(maxLevel - mBaseMipmapLevel + 1);
   ret->mipmapComplete = true;
 
   // -
 
   return ret;
 }
 
 Maybe<const webgl::SampleableInfo> WebGLTexture::CalcSampleableInfo(
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -7,16 +7,17 @@
 #define WEBGL_TEXTURE_H_
 
 #include <algorithm>
 #include <map>
 #include <set>
 #include <vector>
 
 #include "mozilla/Assertions.h"
+#include "mozilla/Casting.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/LinkedList.h"
 #include "nsWrapperCache.h"
 
 #include "CacheInvalidator.h"
 #include "WebGLObjectModel.h"
 #include "WebGLStrongTypes.h"
@@ -264,17 +265,17 @@ class WebGLTexture final : public nsWrap
     GLenum rawTexImageTarget = texImageTarget.get();
     switch (rawTexImageTarget) {
       case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
       case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
       case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
       case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
       case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
       case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-        return rawTexImageTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+        return AutoAssertCast(rawTexImageTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X);
 
       default:
         return 0;
     }
   }
 
   auto& ImageInfoAtFace(uint8_t face, uint32_t level) {
     MOZ_ASSERT(face < mFaceCount);
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -6,16 +6,17 @@
 #include "WebGLTexture.h"
 
 #include <algorithm>
 
 #include "CanvasUtils.h"
 #include "gfxPrefs.h"
 #include "GLBlitHelper.h"
 #include "GLContext.h"
+#include "mozilla/Casting.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/ImageBitmap.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/Unused.h"
@@ -1119,17 +1120,17 @@ void WebGLTexture::TexStorage(TexTarget 
 
     ImageInfoAtFace(0, 0) = newInfo;
     PopulateMipChain(levels - 1);
 
     mBaseMipmapLevel = base_level;
   }
 
   mImmutable = true;
-  mImmutableLevelCount = levels;
+  mImmutableLevelCount = AutoAssertCast(levels);
   ClampLevelBaseAndMax();
 }
 
 ////////////////////////////////////////
 // Tex(Sub)Image
 
 void WebGLTexture::TexImage(TexImageTarget target, GLint level,
                             GLenum internalFormat, const webgl::PackingInfo& pi,
--- a/dom/canvas/WebGLTypes.h
+++ b/dom/canvas/WebGLTypes.h
@@ -5,16 +5,17 @@
 
 #ifndef WEBGLTYPES_H_
 #define WEBGLTYPES_H_
 
 #include <limits>
 
 // Most WebIDL typedefs are identical to their OpenGL counterparts.
 #include "GLTypes.h"
+#include "mozilla/Casting.h"
 
 // Manual reflection of WebIDL typedefs that are different from their
 // OpenGL counterparts.
 typedef int64_t WebGLsizeiptr;
 typedef int64_t WebGLintptr;
 typedef bool WebGLboolean;
 
 // -
@@ -50,16 +51,40 @@ inline void* malloc(const ForbidNarrowin
   return ::malloc(size_t(s));
 }
 
 inline void* calloc(const ForbidNarrowing<size_t> n,
                     const ForbidNarrowing<size_t> size) {
   return ::calloc(size_t(n), size_t(size));
 }
 
+// -
+
+namespace detail {
+
+template<typename From>
+class AutoAssertCastT final {
+  const From mVal;
+
+public:
+  explicit AutoAssertCastT(const From val) : mVal(val) { }
+
+  template<typename To>
+  operator To() const {
+    return AssertedCast<To>(mVal);
+  }
+};
+
+}  // namespace detail
+
+template<typename From>
+inline auto AutoAssertCast(const From val) {
+  return detail::AutoAssertCastT<From>(val);
+}
+
 /*
  * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
  * emulating the vertex attrib 0 array when it's not enabled. Indeed,
  * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
  * desktop OpenGL does not allow that.
  */
 enum class WebGLVertexAttrib0Status : uint8_t {
   Default,                     // default status - no emulation needed
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -212,8 +212,11 @@ LOCAL_INCLUDES += [
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 
 LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow', '-Wno-missing-braces']
+
+if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'):
+    CXXFLAGS += ['-Werror=implicit-int-conversion']