diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp
index f7f4d60ce742ae5b4be6f89ebc7d669a980fe7b1..83f16ce44813ff0d8d19fcf4352a4d2a04a9fb6a 100644
--- a/glslang/MachineIndependent/Scan.cpp
+++ b/glslang/MachineIndependent/Scan.cpp
@@ -155,7 +155,7 @@ void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
 // or no #version was found; otherwise, returns false.  There is no error case, it always
 // succeeds, but will leave version == 0 if no #version was found.
 //
-// Sets versionNotFirstToken based on whether tokens (beyond white space and comments)
+// Sets notFirstToken based on whether tokens (beyond white space and comments)
 // appeared before the #version.
 //
 // N.B. does not attempt to leave input in any particular known state.  The assumption
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index aaadace3bc5855b6792f2cf7450b6ccbd36ead36..075ee8d048b630a72dcd2f87a66953742b7fb710 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -453,6 +453,10 @@ bool CompileDeferred(
     const EShOptimizationLevel optLevel,
     const TBuiltInResource* resources,
     int defaultVersion,         // use 100 for ES environment, 110 for desktop
+    EProfile defaultProfile,
+    // set version/profile to defaultVersion/defaultProfile regardless of the #version
+    // directive in the source code
+    bool forceDefaultVersionAndProfile,
     bool forwardCompatible,     // give errors for use of deprecated features
     EShMessages messages,       // warnings/errors/AST; things to print out
     TIntermediate& intermediate // returned tree, etc.
@@ -497,6 +501,23 @@ bool CompileDeferred(
     bool versionNotFirstToken;
     bool versionNotFirst = userInput.scanVersion(version, profile, versionNotFirstToken);
     bool versionNotFound = version == 0;
+    if (forceDefaultVersionAndProfile) {
+        if (!(messages & EShMsgSuppressWarnings) && !versionNotFound &&
+            (version != defaultVersion || profile != defaultProfile)) {
+            compiler->infoSink.info << "Warning, (version, profile) forced to be ("
+                                    << defaultVersion << ", " << ProfileName(defaultProfile)
+                                    << "), while in source code it is ("
+                                    << version << ", " << ProfileName(profile) << ")\n";
+        }
+
+        if (versionNotFound) {
+            versionNotFirstToken = false;
+            versionNotFirst = false;
+            versionNotFound = false;
+        }
+        version = defaultVersion;
+        profile = defaultProfile;
+    }
     bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, version, profile);
     bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
     bool warnVersionNotFirst = false;
@@ -727,7 +748,7 @@ int ShCompile(
     compiler->infoSink.debug.erase();
 
     TIntermediate intermediate(compiler->getLanguage());
-    bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, "", optLevel, resources, defaultVersion, forwardCompatible, messages, intermediate);
+    bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, "", optLevel, resources, defaultVersion, ENoProfile, false, forwardCompatible, messages, intermediate);
 
     //
     // Call the machine dependent compiler
@@ -1006,7 +1027,7 @@ TShader::~TShader()
 //
 // Returns true for success.
 //
-bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
+bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages messages)
 {
     if (! InitThread())
         return false;
@@ -1016,7 +1037,12 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
     if (! preamble)
         preamble = "";
 
-    return CompileDeferred(compiler, strings, numStrings, nullptr, preamble, EShOptNone, builtInResources, defaultVersion, forwardCompatible, messages, *intermediate);
+    return CompileDeferred(compiler, strings, numStrings, nullptr, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, *intermediate);
+}
+
+bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
+{
+  return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
 }
 
 const char* TShader::getInfoLog()
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 2ffd5c441c513c8980e7273d4fb22aed9747b51e..e7531cb85cfe6ac07f11252c7294978360b6aa9b 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -265,20 +265,6 @@ const char* TParseContext::getPreamble()
     }
 }
 
-//
-// Map from profile enum to externally readable text name.
-//
-const char* ProfileName(EProfile profile)
-{
-    switch (profile) {
-    case ENoProfile:             return "none";        
-    case ECoreProfile:           return "core";
-    case ECompatibilityProfile:  return "compatibility";
-    case EEsProfile:             return "es";
-    default:                     return "unknown profile";
-    }
-}
-
 //
 // When to use requireProfile():
 //
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index 20e00799b193aac516d582bb913458d5875ab488..ee673d3816e97d5cf2601a842688299f381168a0 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -57,6 +57,20 @@ typedef enum {
 
 namespace glslang {
 
+//
+// Map from profile enum to externally readable text name.
+//
+inline const char* ProfileName(EProfile profile)
+{
+    switch (profile) {
+    case ENoProfile:             return "none";
+    case ECoreProfile:           return "core";
+    case ECompatibilityProfile:  return "compatibility";
+    case EEsProfile:             return "es";
+    default:                     return "unknown profile";
+    }
+}
+
 //
 // The behaviors from the GLSL "#extension extension_name : behavior"
 //
diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h
index c1829f7eb120f53fdbe4de485823e6d354168640..e2e7eb21b44aeb08fcee2271ebb80b8457cf4571 100644
--- a/glslang/Public/ShaderLang.h
+++ b/glslang/Public/ShaderLang.h
@@ -35,6 +35,7 @@
 #define _COMPILER_INTERFACE_INCLUDED_
 
 #include "../Include/ResourceLimits.h"
+#include "../MachineIndependent/Versions.h"
 
 #ifdef _WIN32
 #define C_DECL __cdecl
@@ -279,6 +280,9 @@ public:
     virtual ~TShader();
     void setStrings(const char* const* s, int n) { strings = s; numStrings = n; }
     void setPreamble(const char* s) { preamble = s; }
+    bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages);
+    // Equivalent to parse() without a default profile and without forcing defaults.
+    // Provided for backwards compatibility.
     bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages);
 
     const char* getInfoLog();