Refer to GLSL extensions through TExtension enum

Extensions are now referred to by enum values instead of strings most
of the time. This gets rid of unnecessary copying of strings. The code
is easier to work with than before as typoing the extension enum names
will be caught by the compiler.

BUG=angleproject:2147
TEST=angle_unittests

Change-Id: Ifa61b9f86ef03211188fc23bc23a5ce4e4d8c390
Reviewed-on: https://chromium-review.googlesource.com/571002
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler.gypi b/src/compiler.gypi
index a7aad4c..a83b19a 100644
--- a/src/compiler.gypi
+++ b/src/compiler.gypi
@@ -57,6 +57,7 @@
             'compiler/translator/EmulatePrecision.h',
             'compiler/translator/ExpandIntegerPowExpressions.cpp',
             'compiler/translator/ExpandIntegerPowExpressions.h',
+            'compiler/translator/ExtensionBehavior.cpp',
             'compiler/translator/ExtensionBehavior.h',
             'compiler/translator/FindMain.cpp',
             'compiler/translator/FindMain.h',
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 8662bf5..e846d95 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -475,7 +475,7 @@
                 {
                     OutputVariable info;
                     setBuiltInInfoFromSymbolTable("gl_FragData", &info);
-                    if (!::IsExtensionEnabled(mExtensionBehavior, "GL_EXT_draw_buffers"))
+                    if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
                     {
                         info.arraySize = 1;
                     }
@@ -527,7 +527,7 @@
                 else
                 {
                     ASSERT(mShaderType == GL_VERTEX_SHADER &&
-                           IsExtensionEnabled(mExtensionBehavior, "GL_OVR_multiview"));
+                           IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
                 }
                 break;
             default:
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index b01a7c8..c7da64f 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -430,7 +430,8 @@
             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
 
         if (success && (compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
-            parseContext.isMultiviewExtensionEnabled() && getShaderType() != GL_COMPUTE_SHADER)
+            parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
+            getShaderType() != GL_COMPUTE_SHADER)
         {
             DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
                                                         outputType, &symbolTable);
@@ -514,7 +515,7 @@
 
         if (success && shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
             compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
-            IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
+            IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
         {
             EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
                                         &symbolTable, shaderVersion);
diff --git a/src/compiler/translator/DirectiveHandler.cpp b/src/compiler/translator/DirectiveHandler.cpp
index bbcad25..485e666 100644
--- a/src/compiler/translator/DirectiveHandler.cpp
+++ b/src/compiler/translator/DirectiveHandler.cpp
@@ -162,7 +162,7 @@
         return;
     }
 
-    TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
+    TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str()));
     if (iter != mExtensionBehavior.end())
     {
         iter->second = behaviorVal;
diff --git a/src/compiler/translator/ExtensionBehavior.cpp b/src/compiler/translator/ExtensionBehavior.cpp
new file mode 100644
index 0000000..4946793
--- /dev/null
+++ b/src/compiler/translator/ExtensionBehavior.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ExtensionBehavior.cpp: Extension name enumeration and data structures for storing extension
+// behavior.
+
+#include "compiler/translator/ExtensionBehavior.h"
+
+#include "common/debug.h"
+
+#define LIST_EXTENSIONS(OP)             \
+    OP(ARB_texture_rectangle)           \
+    OP(ARM_shader_framebuffer_fetch)    \
+    OP(EXT_blend_func_extended)         \
+    OP(EXT_draw_buffers)                \
+    OP(EXT_frag_depth)                  \
+    OP(EXT_shader_framebuffer_fetch)    \
+    OP(EXT_shader_texture_lod)          \
+    OP(EXT_YUV_target)                  \
+    OP(NV_EGL_stream_consumer_external) \
+    OP(NV_shader_framebuffer_fetch)     \
+    OP(OES_EGL_image_external)          \
+    OP(OES_EGL_image_external_essl3)    \
+    OP(OES_geometry_shader)             \
+    OP(OES_standard_derivatives)        \
+    OP(OVR_multiview)
+
+namespace sh
+{
+
+#define RETURN_EXTENSION_NAME_CASE(ext) \
+    case TExtension::ext:               \
+        return "GL_" #ext;
+
+const char *GetExtensionNameString(TExtension extension)
+{
+    switch (extension)
+    {
+        LIST_EXTENSIONS(RETURN_EXTENSION_NAME_CASE)
+        default:
+            UNREACHABLE();
+            return "";
+    }
+}
+
+#define RETURN_EXTENSION_IF_NAME_MATCHES(ext)  \
+    if (strcmp(extWithoutGLPrefix, #ext) == 0) \
+    {                                          \
+        return TExtension::ext;                \
+    }
+
+TExtension GetExtensionByName(const char *extension)
+{
+    // If first characters of the extension don't equal "GL_", early out.
+    if (strncmp(extension, "GL_", 3) != 0)
+    {
+        return TExtension::UNDEFINED;
+    }
+    const char *extWithoutGLPrefix = extension + 3;
+
+    LIST_EXTENSIONS(RETURN_EXTENSION_IF_NAME_MATCHES)
+
+    return TExtension::UNDEFINED;
+}
+
+const char *GetBehaviorString(TBehavior b)
+{
+    switch (b)
+    {
+        case EBhRequire:
+            return "require";
+        case EBhEnable:
+            return "enable";
+        case EBhWarn:
+            return "warn";
+        case EBhDisable:
+            return "disable";
+        default:
+            return nullptr;
+    }
+}
+
+bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension)
+{
+    ASSERT(extension != TExtension::UNDEFINED);
+    auto iter = extBehavior.find(extension);
+    return iter != extBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire);
+}
+
+}  // namespace sh
diff --git a/src/compiler/translator/ExtensionBehavior.h b/src/compiler/translator/ExtensionBehavior.h
index 179dca3..9a4a4fc 100644
--- a/src/compiler/translator/ExtensionBehavior.h
+++ b/src/compiler/translator/ExtensionBehavior.h
@@ -3,39 +3,57 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
+// ExtensionBehavior.h: Extension name enumeration and data structures for storing extension
+// behavior.
 
 #ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
 #define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
 
 #include <map>
-#include <string>
 
-typedef enum { EBhRequire, EBhEnable, EBhWarn, EBhDisable, EBhUndefined } TBehavior;
-
-inline const char *getBehaviorString(TBehavior b)
+namespace sh
 {
-    switch (b)
-    {
-        case EBhRequire:
-            return "require";
-        case EBhEnable:
-            return "enable";
-        case EBhWarn:
-            return "warn";
-        case EBhDisable:
-            return "disable";
-        default:
-            return nullptr;
-    }
-}
 
-// Mapping between extension name and behavior.
-typedef std::map<std::string, TBehavior> TExtensionBehavior;
-
-inline bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, const char *extension)
+enum class TExtension
 {
-    auto iter = extBehavior.find(extension);
-    return iter != extBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire);
-}
+    UNDEFINED,  // Special value used to indicate no extension.
+
+    ARB_texture_rectangle,
+    ARM_shader_framebuffer_fetch,
+    EXT_blend_func_extended,
+    EXT_draw_buffers,
+    EXT_frag_depth,
+    EXT_shader_framebuffer_fetch,
+    EXT_shader_texture_lod,
+    EXT_YUV_target,
+    NV_EGL_stream_consumer_external,
+    NV_shader_framebuffer_fetch,
+    OES_EGL_image_external,
+    OES_EGL_image_external_essl3,
+    OES_geometry_shader,
+    OES_standard_derivatives,
+    OVR_multiview
+};
+
+enum TBehavior
+{
+    EBhRequire,
+    EBhEnable,
+    EBhWarn,
+    EBhDisable,
+    EBhUndefined
+};
+
+const char *GetExtensionNameString(TExtension extension);
+TExtension GetExtensionByName(const char *extension);
+
+const char *GetBehaviorString(TBehavior b);
+
+// Mapping between extension id and behavior.
+typedef std::map<TExtension, TBehavior> TExtensionBehavior;
+
+bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension);
+
+}  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index f72a6eb..bf026be 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -302,13 +302,13 @@
         /* The *Grad* variants are new to both vertex and fragment shaders; the fragment
          * shader specific pieces are added separately below.
          */
-        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                   "texture2DGradEXT", sampler2D, float2, float2, float2);
-        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                   "texture2DProjGradEXT", sampler2D, float3, float2, float2);
-        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                   "texture2DProjGradEXT", sampler2D, float4, float2, float2);
-        symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                   "textureCubeGradEXT", samplerCube, float3, float3, float3);
     }
 
@@ -324,23 +324,23 @@
 
         if (resources.OES_standard_derivatives)
         {
-            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives",
-                                        genType, genType);
-            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives",
-                                        genType, genType);
-            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives",
-                                        genType, genType);
+            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx,
+                                        TExtension::OES_standard_derivatives, genType, genType);
+            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy,
+                                        TExtension::OES_standard_derivatives, genType, genType);
+            symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth,
+                                        TExtension::OES_standard_derivatives, genType, genType);
         }
 
         if (resources.EXT_shader_texture_lod)
         {
-            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                       "texture2DLodEXT", sampler2D, float2, float1);
-            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                       "texture2DProjLodEXT", sampler2D, float3, float1);
-            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                       "texture2DProjLodEXT", sampler2D, float4, float1);
-            symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4,
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
                                       "textureCubeLodEXT", samplerCube, float3, float1);
         }
     }
@@ -395,19 +395,19 @@
     {
         const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
 
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "texture",
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture",
                                   samplerExternal2DY2YEXT, float2);
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj",
                                   samplerExternal2DY2YEXT, float3);
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj",
                                   samplerExternal2DY2YEXT, float4);
 
         const TType *yuvCscStandardEXT = TCache::getType(EbtYuvCscStandardEXT);
 
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float3, "rgb_2_yuv", float3,
-                                  yuvCscStandardEXT);
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float3, "yuv_2_rgb", float3,
-                                  yuvCscStandardEXT);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "rgb_2_yuv",
+                                  float3, yuvCscStandardEXT);
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "yuv_2_rgb",
+                                  float3, yuvCscStandardEXT);
     }
 
     if (type == GL_FRAGMENT_SHADER)
@@ -437,12 +437,12 @@
         {
             const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
 
-            symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "texture",
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture",
                                       samplerExternal2DY2YEXT, float2, float1);
-            symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
-                                      samplerExternal2DY2YEXT, float3, float1);
-            symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "textureProj",
-                                      samplerExternal2DY2YEXT, float4, float1);
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4,
+                                      "textureProj", samplerExternal2DY2YEXT, float3, float1);
+            symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4,
+                                      "textureProj", samplerExternal2DY2YEXT, float4, float1);
         }
     }
 
@@ -487,7 +487,7 @@
     {
         const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
 
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", int2, "textureSize",
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, int2, "textureSize",
                                   samplerExternal2DY2YEXT, int1);
     }
 
@@ -575,7 +575,7 @@
     {
         const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
 
-        symbolTable.insertBuiltIn(ESSL3_BUILTINS, "GL_EXT_YUV_target", float4, "texelFetch",
+        symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texelFetch",
                                   samplerExternal2DY2YEXT, int2, int1);
     }
 
@@ -678,7 +678,7 @@
 
     if (type == GL_GEOMETRY_SHADER_OES)
     {
-        const char *extension = "GL_OES_geometry_shader";
+        TExtension extension = TExtension::OES_geometry_shader;
         symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, EOpEmitVertex,
                                                          voidType, "EmitVertex");
         symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension,
@@ -727,7 +727,7 @@
                                EbpMedium);
     if (resources.EXT_blend_func_extended)
     {
-        symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
+        symbolTable.insertConstIntExt(COMMON_BUILTINS, TExtension::EXT_blend_func_extended,
                                       "gl_MaxDualSourceDrawBuffersEXT",
                                       resources.MaxDualSourceDrawBuffers, EbpMedium);
     }
@@ -789,7 +789,7 @@
 
     if (resources.OES_geometry_shader)
     {
-        const char *ext = "GL_OES_geometry_shader";
+        TExtension ext = TExtension::OES_geometry_shader;
         symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryInputComponents",
                                       resources.MaxGeometryInputComponents, EbpMedium);
         symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputComponents",
@@ -823,12 +823,12 @@
 
     if (resources.OVR_multiview && type != GL_COMPUTE_SHADER)
     {
-        symbolTable.insertVariableExt(ESSL3_BUILTINS, "GL_OVR_multiview", "gl_ViewID_OVR",
+        symbolTable.insertVariableExt(ESSL3_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR",
                                       TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1));
 
         // ESSL 1.00 doesn't have unsigned integers, so gl_ViewID_OVR is a signed integer in ESSL
         // 1.00. This is specified in the WEBGL_multiview spec.
-        symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_OVR_multiview", "gl_ViewID_OVR",
+        symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR",
                                       TType(EbtInt, EbpHigh, EvqViewIDOVR, 1));
     }
 
@@ -859,18 +859,18 @@
             if (resources.EXT_blend_func_extended)
             {
                 symbolTable.insertVariableExt(
-                    ESSL1_BUILTINS, "GL_EXT_blend_func_extended", "gl_SecondaryFragColorEXT",
+                    ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, "gl_SecondaryFragColorEXT",
                     TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4));
                 TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1);
                 secondaryFragData.makeArray(resources.MaxDualSourceDrawBuffers);
-                symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
+                symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::EXT_blend_func_extended,
                                               "gl_SecondaryFragDataEXT", secondaryFragData);
             }
 
             if (resources.EXT_frag_depth)
             {
                 symbolTable.insertVariableExt(
-                    ESSL1_BUILTINS, "GL_EXT_frag_depth", "gl_FragDepthEXT",
+                    ESSL1_BUILTINS, TExtension::EXT_frag_depth, "gl_FragDepthEXT",
                     TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
                           EvqFragDepthEXT, 1));
             }
@@ -885,28 +885,30 @@
 
                 if (resources.EXT_shader_framebuffer_fetch)
                 {
-                    symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
+                    symbolTable.insertVariableExt(ESSL1_BUILTINS,
+                                                  TExtension::EXT_shader_framebuffer_fetch,
                                                   "gl_LastFragData", lastFragData);
                 }
                 else if (resources.NV_shader_framebuffer_fetch)
                 {
-                    symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
-                                                  "gl_LastFragColor",
-                                                  TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
-                    symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
+                    symbolTable.insertVariableExt(
+                        ESSL1_BUILTINS, TExtension::NV_shader_framebuffer_fetch, "gl_LastFragColor",
+                        TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
+                    symbolTable.insertVariableExt(ESSL1_BUILTINS,
+                                                  TExtension::NV_shader_framebuffer_fetch,
                                                   "gl_LastFragData", lastFragData);
                 }
             }
             else if (resources.ARM_shader_framebuffer_fetch)
             {
-                symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
-                                              "gl_LastFragColorARM",
-                                              TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
+                symbolTable.insertVariableExt(
+                    ESSL1_BUILTINS, TExtension::ARM_shader_framebuffer_fetch, "gl_LastFragColorARM",
+                    TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
             }
 
             if (resources.OES_geometry_shader)
             {
-                const char *extension = "GL_OES_geometry_shader";
+                TExtension extension = TExtension::OES_geometry_shader;
                 symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
                                               TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
                 symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
@@ -950,7 +952,7 @@
 
         case GL_GEOMETRY_SHADER_OES:
         {
-            const char *extension = "GL_OES_geometry_shader";
+            TExtension extension = TExtension::OES_geometry_shader;
 
             // Add built-in interface block gl_PerVertex and the built-in array gl_in.
             // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size.
@@ -996,40 +998,64 @@
 void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior)
 {
     if (resources.OES_standard_derivatives)
-        extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
+    {
+        extBehavior[TExtension::OES_standard_derivatives] = EBhUndefined;
+    }
     if (resources.OES_EGL_image_external)
-        extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
+    {
+        extBehavior[TExtension::OES_EGL_image_external] = EBhUndefined;
+    }
     if (resources.OES_EGL_image_external_essl3)
-        extBehavior["GL_OES_EGL_image_external_essl3"] = EBhUndefined;
+    {
+        extBehavior[TExtension::OES_EGL_image_external_essl3] = EBhUndefined;
+    }
     if (resources.NV_EGL_stream_consumer_external)
-        extBehavior["GL_NV_EGL_stream_consumer_external"] = EBhUndefined;
+    {
+        extBehavior[TExtension::NV_EGL_stream_consumer_external] = EBhUndefined;
+    }
     if (resources.ARB_texture_rectangle)
-        extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
+    {
+        extBehavior[TExtension::ARB_texture_rectangle] = EBhUndefined;
+    }
     if (resources.EXT_blend_func_extended)
-        extBehavior["GL_EXT_blend_func_extended"] = EBhUndefined;
+    {
+        extBehavior[TExtension::EXT_blend_func_extended] = EBhUndefined;
+    }
     if (resources.EXT_draw_buffers)
-        extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+    {
+        extBehavior[TExtension::EXT_draw_buffers] = EBhUndefined;
+    }
     if (resources.EXT_frag_depth)
-        extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
+    {
+        extBehavior[TExtension::EXT_frag_depth] = EBhUndefined;
+    }
     if (resources.EXT_shader_texture_lod)
-        extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
+    {
+        extBehavior[TExtension::EXT_shader_texture_lod] = EBhUndefined;
+    }
     if (resources.EXT_shader_framebuffer_fetch)
-        extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined;
+    {
+        extBehavior[TExtension::EXT_shader_framebuffer_fetch] = EBhUndefined;
+    }
     if (resources.NV_shader_framebuffer_fetch)
-        extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined;
+    {
+        extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined;
+    }
     if (resources.ARM_shader_framebuffer_fetch)
-        extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined;
+    {
+        extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined;
+    }
     if (resources.OVR_multiview)
     {
-        extBehavior["GL_OVR_multiview"] = EBhUndefined;
+        extBehavior[TExtension::OVR_multiview] = EBhUndefined;
     }
     if (resources.EXT_YUV_target)
     {
-        extBehavior["GL_EXT_YUV_target"] = EBhUndefined;
+        extBehavior[TExtension::EXT_YUV_target] = EBhUndefined;
     }
     if (resources.OES_geometry_shader)
     {
-        extBehavior["GL_OES_geometry_shader"] = EBhUndefined;
+        extBehavior[TExtension::OES_geometry_shader] = EBhUndefined;
     }
 }
 
diff --git a/src/compiler/translator/InitializeVariables.cpp b/src/compiler/translator/InitializeVariables.cpp
index bab1b6a..61c02c4 100644
--- a/src/compiler/translator/InitializeVariables.cpp
+++ b/src/compiler/translator/InitializeVariables.cpp
@@ -107,7 +107,7 @@
         {
             initializedSymbol = ReferenceBuiltInVariable(name, symbolTable, shaderVersion);
             if (initializedSymbol->getQualifier() == EvqFragData &&
-                !IsExtensionEnabled(extensionBehavior, "GL_EXT_draw_buffers"))
+                !IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
             {
                 // If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be
                 // written to.
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 53e7656..a16c174 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -130,7 +130,8 @@
     mUsesFrontFacing             = false;
     mUsesPointSize               = false;
     mUsesInstanceID              = false;
-    mHasMultiviewExtensionEnabled = IsExtensionEnabled(mExtensionBehavior, "GL_OVR_multiview");
+    mHasMultiviewExtensionEnabled =
+        IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview);
     mUsesViewID                  = false;
     mUsesVertexID                = false;
     mUsesFragDepth               = false;
@@ -417,9 +418,8 @@
 
     if (mShaderType == GL_FRAGMENT_SHADER)
     {
-        TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers");
-        const bool usingMRTExtension            = (iter != mExtensionBehavior.end() &&
-                                        (iter->second == EBhEnable || iter->second == EBhRequire));
+        const bool usingMRTExtension =
+            IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers);
 
         out << "// Varyings\n";
         out << varyings;
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 86a88d2..51f0e70 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -189,7 +189,6 @@
       mUsesSecondaryOutputs(false),
       mMinProgramTexelOffset(resources.MinProgramTexelOffset),
       mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
-      mMultiviewAvailable(resources.OVR_multiview == 1),
       mComputeShaderLocalSizeDeclared(false),
       mNumViews(-1),
       mMaxNumViews(resources.MaxViewsOVR),
@@ -1146,24 +1145,25 @@
     }
 }
 
-bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
+bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
 {
+    ASSERT(extension != TExtension::UNDEFINED);
     const TExtensionBehavior &extBehavior   = extensionBehavior();
-    TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
+    TExtensionBehavior::const_iterator iter = extBehavior.find(extension);
     if (iter == extBehavior.end())
     {
-        error(line, "extension is not supported", extension.c_str());
+        error(line, "extension is not supported", GetExtensionNameString(extension));
         return false;
     }
     // In GLSL ES, an extension's default behavior is "disable".
     if (iter->second == EBhDisable || iter->second == EBhUndefined)
     {
-        error(line, "extension is disabled", extension.c_str());
+        error(line, "extension is disabled", GetExtensionNameString(extension));
         return false;
     }
     if (iter->second == EBhWarn)
     {
-        warning(line, "extension is being used", extension.c_str());
+        warning(line, "extension is being used", GetExtensionNameString(extension));
         return true;
     }
 
@@ -1212,7 +1212,8 @@
 
     // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
     // parsing steps. So it needs to be checked here.
-    if (isMultiviewExtensionEnabled() && mShaderVersion < 300 && qualifier == EvqVertexIn)
+    if (isExtensionEnabled(TExtension::OVR_multiview) && mShaderVersion < 300 &&
+        qualifier == EvqVertexIn)
     {
         error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
     }
@@ -1626,16 +1627,16 @@
     }
 }
 
-bool TParseContext::supportsExtension(const char *extension)
+bool TParseContext::supportsExtension(TExtension extension)
 {
     const TExtensionBehavior &extbehavior   = extensionBehavior();
     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
     return (iter != extbehavior.end());
 }
 
-bool TParseContext::isExtensionEnabled(const char *extension) const
+bool TParseContext::isExtensionEnabled(TExtension extension) const
 {
-    return ::IsExtensionEnabled(extensionBehavior(), extension);
+    return IsExtensionEnabled(extensionBehavior(), extension);
 }
 
 void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
@@ -1709,8 +1710,7 @@
 
     const TVariable *variable = static_cast<const TVariable *>(symbol);
 
-    if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
-        !variable->getExtension().empty())
+    if (variable->getExtension() != TExtension::UNDEFINED)
     {
         checkCanUseExtension(location, variable->getExtension());
     }
@@ -2954,7 +2954,8 @@
             return;
         }
     }
-    else if (isMultiviewExtensionEnabled() && typeQualifier.qualifier == EvqVertexIn)
+    else if (isExtensionEnabled(TExtension::OVR_multiview) &&
+             typeQualifier.qualifier == EvqVertexIn)
     {
         // This error is only specified in WebGL, but tightens unspecified behavior in the native
         // specification.
@@ -3826,7 +3827,7 @@
         {
             if (baseExpression->getQualifier() == EvqFragData && index > 0)
             {
-                if (!isExtensionEnabled("GL_EXT_draw_buffers"))
+                if (!isExtensionEnabled(TExtension::EXT_draw_buffers))
                 {
                     outOfRangeError(outOfRangeIndexIsError, location,
                                     "array index for gl_FragData must be zero when "
@@ -4059,7 +4060,7 @@
         error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
               qualifierType.c_str());
     }
-    else if (qualifierType == "yuv" && isExtensionEnabled("GL_EXT_YUV_target") &&
+    else if (qualifierType == "yuv" && isExtensionEnabled(TExtension::EXT_YUV_target) &&
              mShaderType == GL_FRAGMENT_SHADER)
     {
         qualifier.yuv = true;
@@ -4129,43 +4130,46 @@
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.imageInternalFormat = EiifR32UI;
     }
-    else if (qualifierType == "points" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "points" && isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.primitiveType = EptPoints;
     }
-    else if (qualifierType == "lines" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "lines" && isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.primitiveType = EptLines;
     }
-    else if (qualifierType == "lines_adjacency" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "lines_adjacency" &&
+             isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.primitiveType = EptLinesAdjacency;
     }
-    else if (qualifierType == "triangles" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "triangles" && isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.primitiveType = EptTriangles;
     }
     else if (qualifierType == "triangles_adjacency" &&
-             isExtensionEnabled("GL_OES_geometry_shader") && mShaderType == GL_GEOMETRY_SHADER_OES)
+             isExtensionEnabled(TExtension::OES_geometry_shader) &&
+             mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.primitiveType = EptTrianglesAdjacency;
     }
-    else if (qualifierType == "line_strip" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "line_strip" && isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
         qualifier.primitiveType = EptLineStrip;
     }
-    else if (qualifierType == "triangle_strip" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "triangle_strip" &&
+             isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
@@ -4317,17 +4321,19 @@
         parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
                        &qualifier.localSize);
     }
-    else if (qualifierType == "num_views" && isMultiviewExtensionEnabled() &&
+    else if (qualifierType == "num_views" && isExtensionEnabled(TExtension::OVR_multiview) &&
              mShaderType == GL_VERTEX_SHADER)
     {
         parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
     }
-    else if (qualifierType == "invocations" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "invocations" &&
+             isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
     }
-    else if (qualifierType == "max_vertices" && isExtensionEnabled("GL_OES_geometry_shader") &&
+    else if (qualifierType == "max_vertices" &&
+             isExtensionEnabled(TExtension::OES_geometry_shader) &&
              mShaderType == GL_GEOMETRY_SHADER_OES)
     {
         parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
@@ -4375,7 +4381,7 @@
     {
         case GL_VERTEX_SHADER:
         {
-            if (mShaderVersion < 300 && !isMultiviewExtensionEnabled())
+            if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview))
             {
                 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
             }
@@ -5496,7 +5502,7 @@
             //
             // A declared function.
             //
-            if (builtIn && !fnCandidate->getExtension().empty())
+            if (builtIn && fnCandidate->getExtension() != TExtension::UNDEFINED)
             {
                 checkCanUseExtension(loc, fnCandidate->getExtension());
             }
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 1719ee1..a13e9a3 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -138,7 +138,7 @@
     void checkIsParameterQualifierValid(const TSourceLoc &line,
                                         const TTypeQualifierBuilder &typeQualifierBuilder,
                                         TType *type);
-    bool checkCanUseExtension(const TSourceLoc &line, const TString &extension);
+    bool checkCanUseExtension(const TSourceLoc &line, TExtension extension);
 
     // Done for all declarations, whether empty or not.
     void declarationQualifierErrorCheck(const sh::TQualifier qualifier,
@@ -168,12 +168,8 @@
     {
         return mDirectiveHandler.extensionBehavior();
     }
-    bool supportsExtension(const char *extension);
-    bool isExtensionEnabled(const char *extension) const;
-    bool isMultiviewExtensionEnabled() const
-    {
-        return mMultiviewAvailable && isExtensionEnabled("GL_OVR_multiview");
-    }
+    bool supportsExtension(TExtension extension);
+    bool isExtensionEnabled(TExtension extension) const;
     void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior);
     void handlePragmaDirective(const TSourceLoc &loc,
                                const char *name,
@@ -580,8 +576,6 @@
     int mMinProgramTexelOffset;
     int mMaxProgramTexelOffset;
 
-    bool mMultiviewAvailable;
-
     // keep track of local group size declared in layout. It should be declared only once.
     bool mComputeShaderLocalSizeDeclared;
     sh::WorkGroupSize mComputeShaderLocalSize;
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 1c2de5c..7885df7 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -43,7 +43,7 @@
 }
 
 TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *n)
-    : uniqueId(symbolTable->nextUniqueId()), name(n)
+    : uniqueId(symbolTable->nextUniqueId()), name(n), extension(TExtension::UNDEFINED)
 {
 }
 
@@ -300,7 +300,7 @@
 }
 
 TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level,
-                                                               const char *ext,
+                                                               TExtension ext,
                                                                const TString *name)
 {
     TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
@@ -332,7 +332,7 @@
 }
 
 TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
-                                           const char *ext,
+                                           TExtension ext,
                                            const char *name,
                                            const TType &type)
 {
@@ -361,7 +361,7 @@
 
 void TSymbolTable::insertBuiltIn(ESymbolLevel level,
                                  TOperator op,
-                                 const char *ext,
+                                 TExtension ext,
                                  const TType *rvalue,
                                  const char *name,
                                  const TType *ptype1,
@@ -530,12 +530,13 @@
     const char *name = GetOperatorString(op);
     ASSERT(strlen(name) > 0);
     insertUnmangledBuiltInName(name, level);
-    insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+    insertBuiltIn(level, op, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, ptype4,
+                  ptype5);
 }
 
 void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
                                    TOperator op,
-                                   const char *ext,
+                                   TExtension ext,
                                    const TType *rvalue,
                                    const TType *ptype1,
                                    const TType *ptype2,
@@ -558,7 +559,7 @@
 }
 
 void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
-                                                        const char *ext,
+                                                        TExtension ext,
                                                         TOperator op,
                                                         const TType *rvalue,
                                                         const char *name)
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 58788a1..bcd51fd 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -35,6 +35,7 @@
 #include <set>
 
 #include "common/angleutils.h"
+#include "compiler/translator/ExtensionBehavior.h"
 #include "compiler/translator/InfoSink.h"
 #include "compiler/translator/IntermNode.h"
 
@@ -74,13 +75,13 @@
     virtual bool isFunction() const { return false; }
     virtual bool isVariable() const { return false; }
     int getUniqueId() const { return uniqueId; }
-    void relateToExtension(const TString &ext) { extension = ext; }
-    const TString &getExtension() const { return extension; }
+    void relateToExtension(TExtension ext) { extension = ext; }
+    TExtension getExtension() const { return extension; }
 
   private:
     const int uniqueId;
     const TString *name;
-    TString extension;
+    TExtension extension;
 };
 
 // Variable, meaning a symbol that's not a function.
@@ -165,8 +166,8 @@
     TFunction(TSymbolTable *symbolTable,
               const TString *name,
               const TType *retType,
-              TOperator tOp   = EOpNull,
-              const char *ext = "")
+              TOperator tOp  = EOpNull,
+              TExtension ext = TExtension::UNDEFINED)
         : TSymbol(symbolTable, name),
           returnType(retType),
           mangledName(nullptr),
@@ -343,12 +344,12 @@
     // declaration failed due to redefinition.
     TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type);
     TVariable *insertVariableExt(ESymbolLevel level,
-                                 const char *ext,
+                                 TExtension ext,
                                  const char *name,
                                  const TType &type);
     TVariable *insertStructType(ESymbolLevel level, TStructure *str);
     TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
-                                                     const char *ext,
+                                                     TExtension ext,
                                                      const TString *name);
 
     bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
@@ -362,7 +363,7 @@
     }
 
     bool insertConstIntExt(ESymbolLevel level,
-                           const char *ext,
+                           TExtension ext,
                            const char *name,
                            int value,
                            TPrecision precision)
@@ -395,7 +396,7 @@
 
     void insertBuiltIn(ESymbolLevel level,
                        TOperator op,
-                       const char *ext,
+                       TExtension ext,
                        const TType *rvalue,
                        const char *name,
                        const TType *ptype1,
@@ -414,11 +415,12 @@
                        const TType *ptype5 = 0)
     {
         insertUnmangledBuiltInName(name, level);
-        insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+        insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3,
+                      ptype4, ptype5);
     }
 
     void insertBuiltIn(ESymbolLevel level,
-                       const char *ext,
+                       TExtension ext,
                        const TType *rvalue,
                        const char *name,
                        const TType *ptype1,
@@ -442,7 +444,7 @@
 
     void insertBuiltInOp(ESymbolLevel level,
                          TOperator op,
-                         const char *ext,
+                         TExtension ext,
                          const TType *rvalue,
                          const TType *ptype1,
                          const TType *ptype2 = 0,
@@ -456,7 +458,7 @@
                                            const char *name);
 
     void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
-                                              const char *ext,
+                                              TExtension ext,
                                               TOperator op,
                                               const TType *rvalue,
                                               const char *name);
@@ -524,7 +526,7 @@
 
     bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
 
-    bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
+    bool insert(ESymbolLevel level, TExtension ext, TSymbol *symbol)
     {
         symbol->relateToExtension(ext);
         return table[level]->insert(symbol);
diff --git a/src/compiler/translator/TranslatorESSL.cpp b/src/compiler/translator/TranslatorESSL.cpp
index b7e30fc..39d0f16 100644
--- a/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/compiler/translator/TranslatorESSL.cpp
@@ -136,16 +136,16 @@
     {
         if (iter->second != EBhUndefined)
         {
-            const bool isMultiview = (iter->first == "GL_OVR_multiview");
+            const bool isMultiview = (iter->first == TExtension::OVR_multiview);
             if (getResources().NV_shader_framebuffer_fetch &&
-                iter->first == "GL_EXT_shader_framebuffer_fetch")
+                iter->first == TExtension::EXT_shader_framebuffer_fetch)
             {
                 sink << "#extension GL_NV_shader_framebuffer_fetch : "
-                     << getBehaviorString(iter->second) << "\n";
+                     << GetBehaviorString(iter->second) << "\n";
             }
-            else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers")
+            else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers)
             {
-                sink << "#extension GL_NV_draw_buffers : " << getBehaviorString(iter->second)
+                sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second)
                      << "\n";
             }
             else if (isMultiview && isMultiviewExtEmulated)
@@ -159,13 +159,13 @@
                     sink << "#extension GL_NV_viewport_array2 : require\n";
                 }
             }
-            else if (iter->first == "GL_OES_geometry_shader")
+            else if (iter->first == TExtension::OES_geometry_shader)
             {
                 sink << "#ifdef GL_OES_geometry_shader\n"
-                     << "#extension GL_OES_geometry_shader : " << getBehaviorString(iter->second)
+                     << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second)
                      << "\n"
                      << "#elif defined GL_EXT_geometry_shader\n"
-                     << "#extension GL_EXT_geometry_shader : " << getBehaviorString(iter->second)
+                     << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second)
                      << "\n";
                 if (iter->second == EBhRequire)
                 {
@@ -177,8 +177,8 @@
             }
             else
             {
-                sink << "#extension " << iter->first << " : " << getBehaviorString(iter->second)
-                     << "\n";
+                sink << "#extension " << GetExtensionNameString(iter->first) << " : "
+                     << GetBehaviorString(iter->second) << "\n";
             }
         }
     }
diff --git a/src/compiler/translator/TranslatorGLSL.cpp b/src/compiler/translator/TranslatorGLSL.cpp
index 22bec80..8a735d8 100644
--- a/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/compiler/translator/TranslatorGLSL.cpp
@@ -130,7 +130,7 @@
     if (getShaderType() == GL_FRAGMENT_SHADER)
     {
         const bool mayHaveESSL1SecondaryOutputs =
-            IsExtensionEnabled(getExtensionBehavior(), "GL_EXT_blend_func_extended") &&
+            IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) &&
             getShaderVersion() == 100;
         const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType());
 
@@ -264,26 +264,26 @@
         {
             // For GLSL output, we don't need to emit most extensions explicitly,
             // but some we need to translate in GL compatibility profile.
-            if (iter.first == "GL_EXT_shader_texture_lod")
+            if (iter.first == TExtension::EXT_shader_texture_lod)
             {
-                sink << "#extension GL_ARB_shader_texture_lod : " << getBehaviorString(iter.second)
+                sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second)
                      << "\n";
             }
 
-            if (iter.first == "GL_EXT_draw_buffers")
+            if (iter.first == TExtension::EXT_draw_buffers)
             {
-                sink << "#extension GL_ARB_draw_buffers : " << getBehaviorString(iter.second)
+                sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second)
                      << "\n";
             }
 
-            if (iter.first == "GL_OES_geometry_shader")
+            if (iter.first == TExtension::OES_geometry_shader)
             {
-                sink << "#extension GL_ARB_geometry_shader4 : " << getBehaviorString(iter.second)
+                sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second)
                      << "\n";
             }
         }
 
-        const bool isMultiview = (iter.first == "GL_OVR_multiview");
+        const bool isMultiview = (iter.first == TExtension::OVR_multiview);
         if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
             (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
         {
diff --git a/src/compiler/translator/ValidateOutputs.cpp b/src/compiler/translator/ValidateOutputs.cpp
index e4ff46f..26f0e81 100644
--- a/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/compiler/translator/ValidateOutputs.cpp
@@ -51,7 +51,7 @@
     : TIntermTraverser(true, false, false),
       mMaxDrawBuffers(maxDrawBuffers),
       mAllowUnspecifiedOutputLocationResolution(
-          IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended")),
+          IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)),
       mUsesFragDepth(false)
 {
 }
diff --git a/src/compiler/translator/glslang.l b/src/compiler/translator/glslang.l
index 0400e30..858ffd9 100644
--- a/src/compiler/translator/glslang.l
+++ b/src/compiler/translator/glslang.l
@@ -80,7 +80,7 @@
 static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
-static int ES3_extension_keyword_else_ident(TParseContext *context, const char *extension, int token);
+static int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token);
 static int uint_constant(TParseContext *context);
 static int int_constant(TParseContext *context);
 static int float_constant(yyscan_t yyscanner);
@@ -198,13 +198,13 @@
 "sampler2DShadow"      { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
 "samplerCubeShadow"    { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); }
 "sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
-"__samplerExternal2DY2YEXT"   { return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", SAMPLEREXTERNAL2DY2YEXT); }
+"__samplerExternal2DY2YEXT"   { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, SAMPLEREXTERNAL2DY2YEXT); }
 
 "struct"       { return STRUCT; }
 
 "layout"  { return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); }
 
-"yuvCscStandardEXT"    { return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", YUVCSCSTANDARDEXT); }
+"yuvCscStandardEXT"    { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); }
 "itu_601"              { return yuvcscstandardext_constant(context); }
 "itu_601_full_range"   { return yuvcscstandardext_constant(context); }
 "itu_709"              { return yuvcscstandardext_constant(context); }
@@ -523,7 +523,7 @@
 
     // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
     // except when multiview extension is enabled
-    if (context->getShaderVersion() < 300 && !context->isMultiviewExtensionEnabled())
+    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview))
     {
         yylval->lex.string = NewPoolTString(yytext);
         return check_type(yyscanner);
@@ -559,7 +559,7 @@
     return token;
 }
 
-int ES3_extension_keyword_else_ident(TParseContext *context, const char* extension, int token)
+int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token)
 {
     struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
     yyscan_t yyscanner = (yyscan_t) context->getScanner();
@@ -641,7 +641,7 @@
     yyscan_t yyscanner = (yyscan_t) context->getScanner();
 
     // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
-    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled("GL_EXT_YUV_target"))
+    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(TExtension::EXT_YUV_target))
     {
         yylval->lex.string = NewPoolTString(yytext);
         return YUVCSCSTANDARDEXTCONSTANT;
@@ -686,7 +686,7 @@
     const TExtensionBehavior& extBehavior = context->extensionBehavior();
     for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
          iter != extBehavior.end(); ++iter) {
-        preprocessor->predefineMacro(iter->first.c_str(), 1);
+        preprocessor->predefineMacro(GetExtensionNameString(iter->first), 1);
     }
     if (context->getFragmentPrecisionHigh())
         preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 8a5e6eb..4285e8d 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -146,7 +146,7 @@
 }
 
 #define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) {  \
-    if (context->getShaderVersion() < 300 && !context->isMultiviewExtensionEnabled()) {  \
+    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) {  \
         context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
     }  \
 }
@@ -279,7 +279,7 @@
         $$ = context->addScalarLiteral(unionArray, @1);
     }
     | YUVCSCSTANDARDEXTCONSTANT {
-        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+        if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) {
            context->error(@1, "unsupported value", $1.string->c_str());
         }
         TConstantUnion *unionArray = new TConstantUnion[1];
@@ -1049,7 +1049,7 @@
         $$.setMatrix(4, 3);
     }
     | YUVCSCSTANDARDEXT {
-        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+        if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) {
             context->error(@1, "unsupported type", "yuvCscStandardEXT");
         }
         $$.initialize(EbtYuvCscStandardEXT, @1);
@@ -1109,20 +1109,20 @@
         $$.initialize(EbtSampler2DArrayShadow, @1);
     }
     | SAMPLER_EXTERNAL_OES {
-        if (!context->supportsExtension("GL_OES_EGL_image_external") &&
-            !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) {
+        if (!context->supportsExtension(TExtension::OES_EGL_image_external) &&
+            !context->supportsExtension(TExtension::NV_EGL_stream_consumer_external)) {
             context->error(@1, "unsupported type", "samplerExternalOES");
         }
         $$.initialize(EbtSamplerExternalOES, @1);
     }
     | SAMPLEREXTERNAL2DY2YEXT {
-        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+        if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) {
             context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT");
         }
         $$.initialize(EbtSamplerExternal2DY2YEXT, @1);
     }
     | SAMPLER2DRECT {
-        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+        if (!context->supportsExtension(TExtension::ARB_texture_rectangle)) {
             context->error(@1, "unsupported type", "sampler2DRect");
         }
         $$.initialize(EbtSampler2DRect, @1);
diff --git a/src/compiler/translator/glslang_lex.cpp b/src/compiler/translator/glslang_lex.cpp
index 87da9ef..d2f9919 100644
--- a/src/compiler/translator/glslang_lex.cpp
+++ b/src/compiler/translator/glslang_lex.cpp
@@ -63,13 +63,37 @@
 
 
 
-    #define yyget_lval yyget_lval
-    #define yyset_lval yyset_lval
+    
+#ifdef yyget_lval
+#define yyget_lval_ALREADY_DEFINED
+#else
+#define yyget_lval yyget_lval
+#endif
+
+    
+#ifdef yyset_lval
+#define yyset_lval_ALREADY_DEFINED
+#else
+#define yyset_lval yyset_lval
+#endif
 
 
 
-    #define yyget_lloc yyget_lloc
-    #define yyset_lloc yyset_lloc
+
+    
+#ifdef yyget_lloc
+#define yyget_lloc_ALREADY_DEFINED
+#else
+#define yyget_lloc yyget_lloc
+#endif
+
+    
+#ifdef yyset_lloc
+#define yyset_lloc_ALREADY_DEFINED
+#else
+#define yyset_lloc yyset_lloc
+#endif
+
 
 
 
@@ -1195,7 +1219,7 @@
 static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
 static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
-static int ES3_extension_keyword_else_ident(TParseContext *context, const char *extension, int token);
+static int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token);
 static int uint_constant(TParseContext *context);
 static int int_constant(TParseContext *context);
 static int float_constant(yyscan_t yyscanner);
@@ -1995,7 +2019,7 @@
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-{ return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", SAMPLEREXTERNAL2DY2YEXT); }
+{ return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, SAMPLEREXTERNAL2DY2YEXT); }
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
@@ -2007,7 +2031,7 @@
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-{ return ES3_extension_keyword_else_ident(context, "GL_EXT_YUV_target", YUVCSCSTANDARDEXT); }
+{ return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); }
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
@@ -2736,6 +2760,8 @@
 			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+		/* "- 2" to take care of EOB's */
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
 	}
 
 	yyg->yy_n_chars += number_to_move;
@@ -3853,7 +3879,7 @@
 
     // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
     // except when multiview extension is enabled
-    if (context->getShaderVersion() < 300 && !context->isMultiviewExtensionEnabled())
+    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview))
     {
         yylval->lex.string = NewPoolTString(yytext);
         return check_type(yyscanner);
@@ -3889,7 +3915,7 @@
     return token;
 }
 
-int ES3_extension_keyword_else_ident(TParseContext *context, const char* extension, int token)
+int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token)
 {
     struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
     yyscan_t yyscanner = (yyscan_t) context->getScanner();
@@ -3971,7 +3997,7 @@
     yyscan_t yyscanner = (yyscan_t) context->getScanner();
 
     // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
-    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled("GL_EXT_YUV_target"))
+    if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(TExtension::EXT_YUV_target))
     {
         yylval->lex.string = NewPoolTString(yytext);
         return YUVCSCSTANDARDEXTCONSTANT;
@@ -4016,7 +4042,7 @@
     const TExtensionBehavior& extBehavior = context->extensionBehavior();
     for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
          iter != extBehavior.end(); ++iter) {
-        preprocessor->predefineMacro(iter->first.c_str(), 1);
+        preprocessor->predefineMacro(GetExtensionNameString(iter->first), 1);
     }
     if (context->getFragmentPrecisionHigh())
         preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 794794b..51dd8e5 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -416,7 +416,7 @@
 }
 
 #define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) {  \
-    if (context->getShaderVersion() < 300 && !context->isMultiviewExtensionEnabled()) {  \
+    if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) {  \
         context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
     }  \
 }
@@ -2586,7 +2586,7 @@
   case 10:
 
     {
-        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+        if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) {
            context->error((yylsp[0]), "unsupported value", (yyvsp[0].lex).string->c_str());
         }
         TConstantUnion *unionArray = new TConstantUnion[1];
@@ -4089,7 +4089,7 @@
   case 189:
 
     {
-        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+        if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) {
             context->error((yylsp[0]), "unsupported type", "yuvCscStandardEXT");
         }
         (yyval.interm.typeSpecifierNonArray).initialize(EbtYuvCscStandardEXT, (yylsp[0]));
@@ -4244,8 +4244,8 @@
   case 208:
 
     {
-        if (!context->supportsExtension("GL_OES_EGL_image_external") &&
-            !context->supportsExtension("GL_NV_EGL_stream_consumer_external")) {
+        if (!context->supportsExtension(TExtension::OES_EGL_image_external) &&
+            !context->supportsExtension(TExtension::NV_EGL_stream_consumer_external)) {
             context->error((yylsp[0]), "unsupported type", "samplerExternalOES");
         }
         (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0]));
@@ -4256,7 +4256,7 @@
   case 209:
 
     {
-        if (!context->isExtensionEnabled("GL_EXT_YUV_target")) {
+        if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) {
             context->error((yylsp[0]), "unsupported type", "__samplerExternal2DY2YEXT");
         }
         (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternal2DY2YEXT, (yylsp[0]));
@@ -4267,7 +4267,7 @@
   case 210:
 
     {
-        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+        if (!context->supportsExtension(TExtension::ARB_texture_rectangle)) {
             context->error((yylsp[0]), "unsupported type", "sampler2DRect");
         }
         (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0]));