Remove recover() from ParseContext

This call is a no-op. The shader parser is intended to almost always
recover from errors, so including it doesn't clarify the code either.
It's simpler to remove it entirely.

BUG=angleproject:911
TEST=angle_unittests

Change-Id: I0feae097c2807c8e9559672e7a3d50a2fc4fbdea
Reviewed-on: https://chromium-review.googlesource.com/367040
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 33ec5bb..b23ee52 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -132,12 +132,6 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-//
-// Track whether errors have occurred.
-//
-void TParseContext::recover()
-{
-}
 
 //
 // Used by flex/bison to output all syntax and parsing errors.
@@ -173,7 +167,6 @@
     if (isError)
     {
         error(loc, reason, token, extraInfo);
-        recover();
     }
     else
     {
@@ -220,33 +213,32 @@
     error(line, " wrong operand types ", op, extraInfo.c_str());
 }
 
-bool TParseContext::precisionErrorCheck(const TSourceLoc &line,
+void TParseContext::precisionErrorCheck(const TSourceLoc &line,
                                         TPrecision precision,
                                         TBasicType type)
 {
     if (!mChecksPrecisionErrors)
-        return false;
+        return;
     if (precision == EbpUndefined)
     {
         switch (type)
         {
             case EbtFloat:
                 error(line, "No precision specified for (float)", "");
-                return true;
+                return;
             case EbtInt:
             case EbtUInt:
                 UNREACHABLE();  // there's always a predeclared qualifier
                 error(line, "No precision specified (int)", "");
-                return true;
+                return;
             default:
                 if (IsSampler(type))
                 {
                     error(line, "No precision specified (sampler)", "");
-                    return true;
+                    return;
                 }
         }
     }
-    return false;
 }
 
 //
@@ -409,55 +401,36 @@
     return true;
 }
 
-//
 // Both test, and if necessary spit out an error, to see if the node is really
 // a constant.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::constErrorCheck(TIntermTyped *node)
+void TParseContext::constErrorCheck(TIntermTyped *node)
 {
-    if (node->getQualifier() == EvqConst)
-        return false;
-
-    error(node->getLine(), "constant expression required", "");
-
-    return true;
+    if (node->getQualifier() != EvqConst)
+    {
+        error(node->getLine(), "constant expression required", "");
+    }
 }
 
-//
 // Both test, and if necessary spit out an error, to see if the node is really
 // an integer.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::integerErrorCheck(TIntermTyped *node, const char *token)
+void TParseContext::integerErrorCheck(TIntermTyped *node, const char *token)
 {
-    if (node->isScalarInt())
-        return false;
-
-    error(node->getLine(), "integer expression required", token);
-
-    return true;
+    if (!node->isScalarInt())
+    {
+        error(node->getLine(), "integer expression required", token);
+    }
 }
 
-//
 // Both test, and if necessary spit out an error, to see if we are currently
 // globally scoped.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char *token)
+void TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char *token)
 {
-    if (global)
-        return false;
-
-    error(line, "only allowed at global scope", token);
-
-    return true;
+    if (!global)
+    {
+        error(line, "only allowed at global scope", token);
+    }
 }
 
-//
 // For now, keep it simple:  if it starts "gl_", it's reserved, independent
 // of scope.  Except, if the symbol table is at the built-in push-level,
 // which is when we are parsing built-ins.
@@ -671,35 +644,23 @@
 }
 
 // This function checks to see if the node (for the expression) contains a scalar boolean expression
-// or not
-//
-// returns true in case of an error
-//
-bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *type)
+// or not.
+void TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *type)
 {
     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
     {
         error(line, "boolean expression expected", "");
-        return true;
     }
-
-    return false;
 }
 
 // This function checks to see if the node (for the expression) contains a scalar boolean expression
-// or not
-//
-// returns true in case of an error
-//
-bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pType)
+// or not.
+void TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pType)
 {
     if (pType.type != EbtBool || pType.isAggregate())
     {
         error(line, "boolean expression expected", "");
-        return true;
     }
-
-    return false;
 }
 
 bool TParseContext::samplerErrorCheck(const TSourceLoc &line,
@@ -727,19 +688,16 @@
     return false;
 }
 
-bool TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType)
+void TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType)
 {
     if (pType.layoutQualifier.location != -1)
     {
         error(line, "location must only be specified for a single input or output variable",
               "location");
-        return true;
     }
-
-    return false;
 }
 
-bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line,
+void TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line,
                                                TQualifier qualifier,
                                                const TType &type)
 {
@@ -747,10 +705,7 @@
         IsSampler(type.getBasicType()))
     {
         error(line, "samplers cannot be output parameters", type.getBasicString());
-        return true;
     }
-
-    return false;
 }
 
 bool TParseContext::containsSampler(const TType &type)
@@ -771,12 +726,8 @@
     return false;
 }
 
-//
 // Do size checking for an array type's size.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size)
+void TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size)
 {
     TIntermConstantUnion *constant = expr->getAsConstantUnion();
 
@@ -787,7 +738,7 @@
     {
         error(line, "array size must be a constant integer expression", "");
         size = 1;
-        return true;
+        return;
     }
 
     unsigned int unsignedSize = 0;
@@ -805,7 +756,7 @@
         {
             error(line, "array size must be non-negative", "");
             size = 1;
-            return true;
+            return;
         }
 
         unsignedSize = static_cast<unsigned int>(size);
@@ -815,7 +766,7 @@
     {
         error(line, "array size must be greater than zero", "");
         size = 1;
-        return true;
+        return;
     }
 
     // The size of arrays is restricted here to prevent issues further down the
@@ -827,13 +778,10 @@
     {
         error(line, "array size too large", "");
         size = 1;
-        return true;
+        return;
     }
-
-    return false;
 }
 
-//
 // See if this qualifier can be an array.
 //
 // Returns true if there is an error.
@@ -851,7 +799,6 @@
     return false;
 }
 
-//
 // See if this type can be an array.
 //
 // Returns true if there is an error.
@@ -879,12 +826,8 @@
     return false;
 }
 
-//
 // Enforce non-initializer type/qualifier rules.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::nonInitErrorCheck(const TSourceLoc &line,
+void TParseContext::nonInitErrorCheck(const TSourceLoc &line,
                                       const TString &identifier,
                                       TPublicType *type)
 {
@@ -907,15 +850,12 @@
         {
             error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
         }
-
-        return true;
+        return;
     }
     if (type->isUnsizedArray())
     {
         error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
-        return true;
     }
-    return false;
 }
 
 // Do some simple checks that are shared between all variable declarations,
@@ -969,7 +909,7 @@
     return true;
 }
 
-bool TParseContext::paramErrorCheck(const TSourceLoc &line,
+void TParseContext::paramErrorCheck(const TSourceLoc &line,
                                     TQualifier qualifier,
                                     TQualifier paramQualifier,
                                     TType *type)
@@ -977,21 +917,19 @@
     if (qualifier != EvqConst && qualifier != EvqTemporary)
     {
         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
-        return true;
+        return;
     }
     if (qualifier == EvqConst && paramQualifier != EvqIn)
     {
         error(line, "qualifier not allowed with ", getQualifierString(qualifier),
               getQualifierString(paramQualifier));
-        return true;
+        return;
     }
 
     if (qualifier == EvqConst)
         type->setQualifier(EvqConstReadOnly);
     else
         type->setQualifier(paramQualifier);
-
-    return false;
 }
 
 bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString &extension)
@@ -1020,8 +958,7 @@
 
 // These checks are common for all declarations starting a declarator list, and declarators that
 // follow an empty declaration.
-//
-bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
+void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
                                                 const TSourceLoc &identifierLocation)
 {
     switch (publicType.qualifier)
@@ -1036,7 +973,7 @@
             {
                 error(identifierLocation, "cannot be used with a structure",
                       getQualifierString(publicType.qualifier));
-                return true;
+                return;
             }
 
         default:
@@ -1046,7 +983,7 @@
     if (publicType.qualifier != EvqUniform &&
         samplerErrorCheck(identifierLocation, publicType, "samplers must be uniform"))
     {
-        return true;
+        return;
     }
 
     // check for layout qualifier issues
@@ -1057,7 +994,7 @@
         error(identifierLocation, "layout qualifier",
               getMatrixPackingString(layoutQualifier.matrixPacking),
               "only valid for interface blocks");
-        return true;
+        return;
     }
 
     if (layoutQualifier.blockStorage != EbsUnspecified)
@@ -1065,29 +1002,23 @@
         error(identifierLocation, "layout qualifier",
               getBlockStorageString(layoutQualifier.blockStorage),
               "only valid for interface blocks");
-        return true;
+        return;
     }
 
-    if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
-        layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
+    if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
     {
-        return true;
+        layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier);
     }
-
-    return false;
 }
 
-bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location,
+void TParseContext::layoutLocationErrorCheck(const TSourceLoc &location,
                                              const TLayoutQualifier &layoutQualifier)
 {
     if (layoutQualifier.location != -1)
     {
         error(location, "invalid layout qualifier:", "location",
               "only valid on program inputs and outputs");
-        return true;
     }
-
-    return false;
 }
 
 void TParseContext::layoutSupportedErrorCheck(const TSourceLoc &location,
@@ -1098,7 +1029,6 @@
     if (mShaderVersion < versionRequired)
     {
         error(location, "invalid layout qualifier:", layoutQualifierName.c_str(), "not supported");
-        recover();
     }
 }
 
@@ -1119,7 +1049,7 @@
     return false;
 }
 
-bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
+void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
                                                  TIntermAggregate *aggregate)
 {
     for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
@@ -1132,12 +1062,10 @@
             {
                 error(node->getLine(),
                       "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
-                recover();
-                return true;
+                return;
             }
         }
     }
-    return false;
 }
 
 void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier,
@@ -1146,7 +1074,6 @@
     if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
     {
         error(invariantLocation, "Only out variables can be invariant.", "invariant");
-        recover();
     }
 }
 
@@ -1215,22 +1142,19 @@
     if (!symbol)
     {
         error(location, "undeclared identifier", name->c_str());
-        recover();
     }
     else if (!symbol->isVariable())
     {
         error(location, "variable expected", name->c_str());
-        recover();
     }
     else
     {
         variable = static_cast<const TVariable *>(symbol);
 
         if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
-            !variable->getExtension().empty() &&
-            extensionErrorCheck(location, variable->getExtension()))
+            !variable->getExtension().empty())
         {
-            recover();
+            extensionErrorCheck(location, variable->getExtension());
         }
 
         // Reject shaders using both gl_FragData and gl_FragColor
@@ -1262,7 +1186,6 @@
                     " and (gl_FragColor, gl_SecondaryFragColorEXT)";
             }
             error(location, errorMessage, name->c_str());
-            recover();
         }
 
         // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
@@ -1463,17 +1386,13 @@
     returnType.invariant       = invariant;
     returnType.layoutQualifier = layoutQualifier;
 
-    if (layoutWorkGroupSizeErrorCheck(typeSpecifier.line, layoutQualifier))
-    {
-        recover();
-    }
+    layoutWorkGroupSizeErrorCheck(typeSpecifier.line, layoutQualifier);
 
     if (mShaderVersion < 300)
     {
         if (typeSpecifier.array)
         {
             error(typeSpecifier.line, "not supported", "first-class array");
-            recover();
             returnType.clearArrayness();
         }
 
@@ -1481,24 +1400,19 @@
             (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
         {
             error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
-            recover();
         }
 
         if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
             (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
         {
             error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
-            recover();
         }
     }
     else
     {
         if (!layoutQualifier.isEmpty())
         {
-            if (globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout"))
-            {
-                recover();
-            }
+            globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout");
         }
         if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
         {
@@ -1508,7 +1422,6 @@
         {
             error(typeSpecifier.line, "'in' can be only used to specify the local group size",
                   "in");
-            recover();
         }
     }
 
@@ -1523,7 +1436,6 @@
     if (type.type == EbtBool)
     {
         error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
-        recover();
     }
 
     // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
@@ -1534,7 +1446,6 @@
             if (type.array)
             {
                 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
-                recover();
             }
             // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
             return;
@@ -1543,7 +1454,6 @@
             if (type.isMatrix())
             {
                 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
-                recover();
             }
             // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
             return;
@@ -1560,7 +1470,6 @@
     {
         error(qualifierLocation, "must use 'flat' interpolation here",
               getQualifierString(qualifier));
-        recover();
     }
 
     if (type.type == EbtStruct)
@@ -1572,25 +1481,21 @@
         {
             error(qualifierLocation, "cannot be an array of structures",
                   getQualifierString(qualifier));
-            recover();
         }
         if (type.isStructureContainingArrays())
         {
             error(qualifierLocation, "cannot be a structure containing an array",
                   getQualifierString(qualifier));
-            recover();
         }
         if (type.isStructureContainingType(EbtStruct))
         {
             error(qualifierLocation, "cannot be a structure containing a structure",
                   getQualifierString(qualifier));
-            recover();
         }
         if (type.isStructureContainingType(EbtBool))
         {
             error(qualifierLocation, "cannot be a structure containing a bool",
                   getQualifierString(qualifier));
-            recover();
         }
     }
 }
@@ -1618,15 +1523,12 @@
     }
     else
     {
-        if (singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
-            recover();
+        singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
 
-        if (nonInitErrorCheck(identifierOrTypeLocation, identifier, &publicType))
-            recover();
+        nonInitErrorCheck(identifierOrTypeLocation, identifier, &publicType);
 
         TVariable *variable = nullptr;
-        if (!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
-            recover();
+        declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable);
 
         if (variable && symbol)
             symbol->setId(variable->getUniqueId());
@@ -1643,32 +1545,25 @@
 {
     mDeferredSingleDeclarationErrorCheck = false;
 
-    if (singleDeclarationErrorCheck(publicType, identifierLocation))
-        recover();
+    singleDeclarationErrorCheck(publicType, identifierLocation);
 
-    if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
-        recover();
+    nonInitErrorCheck(identifierLocation, identifier, &publicType);
 
-    if (arrayTypeErrorCheck(indexLocation, publicType) ||
-        arrayQualifierErrorCheck(indexLocation, publicType))
+    if (!arrayTypeErrorCheck(indexLocation, publicType))
     {
-        recover();
+        arrayQualifierErrorCheck(indexLocation, publicType);
     }
 
     TType arrayType(publicType);
 
     int size;
-    if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
-    {
-        recover();
-    }
+    arraySizeErrorCheck(identifierLocation, indexExpression, size);
     // Make the type an array even if size check failed.
     // This ensures useless error messages regarding the variable's non-arrayness won't follow.
     arrayType.setArraySize(size);
 
     TVariable *variable = nullptr;
-    if (!declareVariable(identifierLocation, identifier, arrayType, &variable))
-        recover();
+    declareVariable(identifierLocation, identifier, arrayType, &variable);
 
     TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
     if (variable && symbol)
@@ -1685,8 +1580,7 @@
 {
     mDeferredSingleDeclarationErrorCheck = false;
 
-    if (singleDeclarationErrorCheck(publicType, identifierLocation))
-        recover();
+    singleDeclarationErrorCheck(publicType, identifierLocation);
 
     TIntermNode *intermNode = nullptr;
     if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
@@ -1698,7 +1592,6 @@
     }
     else
     {
-        recover();
         return nullptr;
     }
 }
@@ -1714,13 +1607,11 @@
 {
     mDeferredSingleDeclarationErrorCheck = false;
 
-    if (singleDeclarationErrorCheck(publicType, identifierLocation))
-        recover();
+    singleDeclarationErrorCheck(publicType, identifierLocation);
 
-    if (arrayTypeErrorCheck(indexLocation, publicType) ||
-        arrayQualifierErrorCheck(indexLocation, publicType))
+    if (!arrayTypeErrorCheck(indexLocation, publicType))
     {
-        recover();
+        arrayQualifierErrorCheck(indexLocation, publicType);
     }
 
     TPublicType arrayType(publicType);
@@ -1728,10 +1619,9 @@
     int size = 0;
     // If indexExpression is nullptr, then the array will eventually get its size implicitly from
     // the initializer.
-    if (indexExpression != nullptr &&
-        arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    if (indexExpression != nullptr)
     {
-        recover();
+        arraySizeErrorCheck(identifierLocation, indexExpression, size);
     }
     // Make the type an array even if size check failed.
     // This ensures useless error messages regarding the variable's non-arrayness won't follow.
@@ -1745,7 +1635,6 @@
     }
     else
     {
-        recover();
         return nullptr;
     }
 }
@@ -1756,15 +1645,11 @@
                                                            const TSymbol *symbol)
 {
     // invariant declaration
-    if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
-    {
-        recover();
-    }
+    globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying");
 
     if (!symbol)
     {
         error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
-        recover();
         return nullptr;
     }
     else
@@ -1774,7 +1659,6 @@
         {
             error(identifierLoc, "identifier should not be declared as invariant",
                   identifier->c_str());
-            recover();
             return nullptr;
         }
         symbolTable.addInvariantVarying(std::string(identifier->c_str()));
@@ -1799,20 +1683,16 @@
     // not performed.
     if (mDeferredSingleDeclarationErrorCheck)
     {
-        if (singleDeclarationErrorCheck(publicType, identifierLocation))
-            recover();
+        singleDeclarationErrorCheck(publicType, identifierLocation);
         mDeferredSingleDeclarationErrorCheck = false;
     }
 
-    if (locationDeclaratorListCheck(identifierLocation, publicType))
-        recover();
+    locationDeclaratorListCheck(identifierLocation, publicType);
 
-    if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
-        recover();
+    nonInitErrorCheck(identifierLocation, identifier, &publicType);
 
     TVariable *variable = nullptr;
-    if (!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
-        recover();
+    declareVariable(identifierLocation, identifier, TType(publicType), &variable);
 
     TIntermSymbol *symbol =
         intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
@@ -1833,35 +1713,24 @@
     // not performed.
     if (mDeferredSingleDeclarationErrorCheck)
     {
-        if (singleDeclarationErrorCheck(publicType, identifierLocation))
-            recover();
+        singleDeclarationErrorCheck(publicType, identifierLocation);
         mDeferredSingleDeclarationErrorCheck = false;
     }
 
-    if (locationDeclaratorListCheck(identifierLocation, publicType))
-        recover();
+    locationDeclaratorListCheck(identifierLocation, publicType);
 
-    if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
-        recover();
+    nonInitErrorCheck(identifierLocation, identifier, &publicType);
 
-    if (arrayTypeErrorCheck(arrayLocation, publicType) ||
-        arrayQualifierErrorCheck(arrayLocation, publicType))
-    {
-        recover();
-    }
-    else
+    if (!arrayTypeErrorCheck(arrayLocation, publicType) &&
+        !arrayQualifierErrorCheck(arrayLocation, publicType))
     {
         TType arrayType = TType(publicType);
         int size;
-        if (arraySizeErrorCheck(arrayLocation, indexExpression, size))
-        {
-            recover();
-        }
+        arraySizeErrorCheck(arrayLocation, indexExpression, size);
         arrayType.setArraySize(size);
 
         TVariable *variable = nullptr;
-        if (!declareVariable(identifierLocation, identifier, arrayType, &variable))
-            recover();
+        declareVariable(identifierLocation, identifier, arrayType, &variable);
 
         TIntermSymbol *symbol =
             intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
@@ -1885,13 +1754,11 @@
     // not performed.
     if (mDeferredSingleDeclarationErrorCheck)
     {
-        if (singleDeclarationErrorCheck(publicType, identifierLocation))
-            recover();
+        singleDeclarationErrorCheck(publicType, identifierLocation);
         mDeferredSingleDeclarationErrorCheck = false;
     }
 
-    if (locationDeclaratorListCheck(identifierLocation, publicType))
-        recover();
+    locationDeclaratorListCheck(identifierLocation, publicType);
 
     TIntermNode *intermNode = nullptr;
     if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
@@ -1910,7 +1777,6 @@
     }
     else
     {
-        recover();
         return nullptr;
     }
 }
@@ -1928,18 +1794,15 @@
     // not performed.
     if (mDeferredSingleDeclarationErrorCheck)
     {
-        if (singleDeclarationErrorCheck(publicType, identifierLocation))
-            recover();
+        singleDeclarationErrorCheck(publicType, identifierLocation);
         mDeferredSingleDeclarationErrorCheck = false;
     }
 
-    if (locationDeclaratorListCheck(identifierLocation, publicType))
-        recover();
+    locationDeclaratorListCheck(identifierLocation, publicType);
 
-    if (arrayTypeErrorCheck(indexLocation, publicType) ||
-        arrayQualifierErrorCheck(indexLocation, publicType))
+    if (!arrayTypeErrorCheck(indexLocation, publicType))
     {
-        recover();
+        arrayQualifierErrorCheck(indexLocation, publicType);
     }
 
     TPublicType arrayType(publicType);
@@ -1947,10 +1810,9 @@
     int size = 0;
     // If indexExpression is nullptr, then the array will eventually get its size implicitly from
     // the initializer.
-    if (indexExpression != nullptr &&
-        arraySizeErrorCheck(identifierLocation, indexExpression, size))
+    if (indexExpression != nullptr)
     {
-        recover();
+        arraySizeErrorCheck(identifierLocation, indexExpression, size);
     }
     // Make the type an array even if size check failed.
     // This ensures useless error messages regarding the variable's non-arrayness won't follow.
@@ -1971,28 +1833,24 @@
     }
     else
     {
-        recover();
         return nullptr;
     }
 }
 
 void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
 {
-
     const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
 
     // It should never be the case, but some strange parser errors can send us here.
     if (layoutQualifier.isEmpty())
     {
         error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
-        recover();
         return;
     }
 
     if (!layoutQualifier.isCombinationValid())
     {
         error(typeQualifier.line, "invalid combination:", "layout");
-        recover();
         return;
     }
 
@@ -2003,21 +1861,18 @@
         {
             error(typeQualifier.line, "Work group size does not match the previous declaration",
                   "layout");
-            recover();
             return;
         }
 
         if (mShaderVersion < 310)
         {
             error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
-            recover();
             return;
         }
 
         if (!layoutQualifier.isGroupSizeSpecified())
         {
             error(typeQualifier.line, "No local work group size specified", "layout");
-            recover();
             return;
         }
 
@@ -2043,7 +1898,6 @@
 
                     error(typeQualifier.line, "invalid value:", getLocalSizeString(i),
                           errorMessage.c_str());
-                    recover();
                     return;
                 }
             }
@@ -2056,7 +1910,6 @@
 
         if (layoutWorkGroupSizeErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
         {
-            recover();
             return;
         }
 
@@ -2064,7 +1917,6 @@
         {
             error(typeQualifier.line, "invalid qualifier:",
                   getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
-            recover();
             return;
         }
 
@@ -2072,15 +1924,10 @@
         {
             error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
                   "layout");
-            recover();
             return;
         }
 
-        if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
-        {
-            recover();
-            return;
-        }
+        layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier);
 
         if (layoutQualifier.matrixPacking != EmpUnspecified)
         {
@@ -2107,7 +1954,6 @@
         // ESSL 1.00.17 section 4.2.7.
         // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
         error(location, "duplicate function prototype declarations are not allowed", "function");
-        recover();
     }
     symbolTableFunction->setHasPrototypeDeclaration();
 
@@ -2142,7 +1988,6 @@
     {
         // ESSL 3.00.4 section 4.2.4.
         error(location, "local function prototype declarations are not allowed", "function");
-        recover();
     }
 
     return prototype;
@@ -2158,7 +2003,6 @@
     if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
     {
         error(location, "function does not return a value:", "", function.getName().c_str());
-        recover();
     }
 
     TIntermAggregate *aggregate =
@@ -2182,7 +2026,6 @@
     if (builtIn)
     {
         error(location, "built-in functions cannot be redefined", function->getName().c_str());
-        recover();
     }
 
     TFunction *prevDec =
@@ -2196,7 +2039,6 @@
     {
         // Then this function already has a body.
         error(location, "function already has a body", function->getName().c_str());
-        recover();
     }
     prevDec->setDefined();
     //
@@ -2212,13 +2054,11 @@
         if (function->getParamCount() > 0)
         {
             error(location, "function cannot take any parameter(s)", function->getName().c_str());
-            recover();
         }
         if (function->getReturnType().getBasicType() != EbtVoid)
         {
             error(location, "", function->getReturnType().getBasicString(),
                   "main function cannot return a value");
-            recover();
         }
     }
 
@@ -2249,7 +2089,6 @@
             if (!symbolTable.declare(variable))
             {
                 error(location, "redefinition", variable->getName().c_str());
-                recover();
                 paramNodes = intermediate.growAggregate(
                     paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
                 continue;
@@ -2293,7 +2132,6 @@
         // Therefore overloading or redefining builtin functions is an error.
         error(location, "Name of a built-in function cannot be redeclared as function",
               function->getName().c_str());
-        recover();
     }
     else if (prevDec)
     {
@@ -2301,7 +2139,6 @@
         {
             error(location, "overloaded functions must have the same return type",
                   function->getReturnType().getBasicString());
-            recover();
         }
         for (size_t i = 0; i < prevDec->getParamCount(); ++i)
         {
@@ -2310,7 +2147,6 @@
             {
                 error(location, "overloaded functions must have the same parameter qualifiers",
                       function->getParam(i).type->getQualifierString());
-                recover();
             }
         }
     }
@@ -2324,7 +2160,6 @@
         if (!prevSym->isFunction())
         {
             error(location, "redefinition", function->getName().c_str(), "function");
-            recover();
         }
     }
     else
@@ -2355,18 +2190,13 @@
     {
         error(location, "no qualifiers allowed for function return",
               getQualifierString(type.qualifier));
-        recover();
     }
     if (!type.layoutQualifier.isEmpty())
     {
         error(location, "no qualifiers allowed for function return", "layout");
-        recover();
     }
     // make sure a sampler is not involved as well...
-    if (samplerErrorCheck(location, type, "samplers can't be function return values"))
-    {
-        recover();
-    }
+    samplerErrorCheck(location, type, "samplers can't be function return values");
     if (mShaderVersion < 300)
     {
         // Array return values are forbidden, but there's also no valid syntax for declaring array
@@ -2378,7 +2208,6 @@
             // ESSL 1.00.17 section 6.1 Function Definitions
             error(location, "structures containing arrays can't be function return values",
                   TType(type).getCompleteString().c_str());
-            recover();
         }
     }
 
@@ -2393,7 +2222,6 @@
     {
         error(publicType.line, "constructor can't be a structure definition",
               getBasicString(publicType.type));
-        recover();
     }
 
     TOperator op = EOpNull;
@@ -2407,7 +2235,6 @@
         if (op == EOpNull)
         {
             error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
-            recover();
             publicType.type = EbtFloat;
             op              = EOpConstructFloat;
         }
@@ -2445,7 +2272,6 @@
             if (!argType.sameElementType(*type))
             {
                 error(line, "Array constructor argument has an incorrect type", "Error");
-                recover();
                 return nullptr;
             }
         }
@@ -2461,7 +2287,6 @@
             {
                 error(line, "Structure constructor arguments do not match structure fields",
                       "Error");
-                recover();
 
                 return 0;
             }
@@ -2579,9 +2404,7 @@
     else
     {
         error(line, "Cannot offset into the structure", "Error");
-        recover();
-
-        return 0;
+        return nullptr;
     }
 
     return typedNode;
@@ -2599,21 +2422,16 @@
                                                    TIntermTyped *arrayIndex,
                                                    const TSourceLoc &arrayIndexLine)
 {
-    if (reservedErrorCheck(nameLine, blockName))
-        recover();
+    reservedErrorCheck(nameLine, blockName);
 
     if (typeQualifier.qualifier != EvqUniform)
     {
         error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
               "interface blocks must be uniform");
-        recover();
     }
 
     TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
-    if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
-    {
-        recover();
-    }
+    layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier);
 
     if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
     {
@@ -2625,16 +2443,12 @@
         blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
     }
 
-    if (layoutWorkGroupSizeErrorCheck(nameLine, blockLayoutQualifier))
-    {
-        recover();
-    }
+    layoutWorkGroupSizeErrorCheck(nameLine, blockLayoutQualifier);
 
     TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
     if (!symbolTable.declare(blockNameSymbol))
     {
         error(nameLine, "redefinition", blockName.c_str(), "interface block name");
-        recover();
     }
 
     // check for sampler types and apply layout qualifiers
@@ -2646,7 +2460,6 @@
         {
             error(field->line(), "unsupported type", fieldType->getBasicString(),
                   "sampler types are not allowed in interface blocks");
-            recover();
         }
 
         const TQualifier qualifier = fieldType->getQualifier();
@@ -2658,22 +2471,17 @@
             default:
                 error(field->line(), "invalid qualifier on interface block member",
                       getQualifierString(qualifier));
-                recover();
                 break;
         }
 
         // check layout qualifiers
         TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
-        if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
-        {
-            recover();
-        }
+        layoutLocationErrorCheck(field->line(), fieldLayoutQualifier);
 
         if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
         {
             error(field->line(), "invalid layout qualifier:",
                   getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
-            recover();
         }
 
         if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
@@ -2694,8 +2502,7 @@
     int arraySize = 0;
     if (arrayIndex != NULL)
     {
-        if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
-            recover();
+        arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize);
     }
 
     TInterfaceBlock *interfaceBlock =
@@ -2724,14 +2531,12 @@
             {
                 error(field->line(), "redefinition", field->name().c_str(),
                       "interface block member name");
-                recover();
             }
         }
     }
     else
     {
-        if (reservedErrorCheck(instanceLine, *instanceName))
-            recover();
+        reservedErrorCheck(instanceLine, *instanceName);
 
         // add a symbol for this interface block
         TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
@@ -2741,7 +2546,6 @@
         {
             error(instanceLine, "redefinition", instanceName->c_str(),
                   "interface block instance name");
-            recover();
         }
 
         symbolId   = instanceTypeDef->getUniqueId();
@@ -2757,7 +2561,7 @@
     return aggregate;
 }
 
-bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
+void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
 {
     ++mStructNestingLevel;
 
@@ -2767,10 +2571,7 @@
     if (mStructNestingLevel > 1)
     {
         error(line, "", "Embedded struct definitions are not allowed");
-        return true;
     }
-
-    return false;
 }
 
 void TParseContext::exitStructDeclaration()
@@ -2831,7 +2632,6 @@
         {
             error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
         }
-        recover();
     }
 
     TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
@@ -2847,18 +2647,15 @@
             error(
                 location, "", "[",
                 "array indexes for interface blocks arrays must be constant integral expressions");
-            recover();
         }
         else if (baseExpression->getQualifier() == EvqFragmentOut)
         {
             error(location, "", "[",
                   "array indexes for fragment outputs must be constant integral expressions");
-            recover();
         }
         else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
         {
             error(location, "", "[", "array index for gl_FragData must be constant zero");
-            recover();
         }
     }
 
@@ -2929,7 +2726,6 @@
                         {
                             error(location, "", "[",
                                   "array index for gl_FragData must be constant zero");
-                            recover();
                         }
                         safeIndex = 0;
                     }
@@ -3047,7 +2843,6 @@
     if (baseExpression->isArray())
     {
         error(fieldLocation, "cannot apply dot operator to an array", ".");
-        recover();
     }
 
     if (baseExpression->isVector())
@@ -3058,7 +2853,6 @@
         {
             fields.num        = 1;
             fields.offsets[0] = 0;
-            recover();
         }
 
         if (baseExpression->getAsConstantUnion())
@@ -3075,7 +2869,6 @@
         }
         if (indexedExpression == nullptr)
         {
-            recover();
             indexedExpression = baseExpression;
         }
         else
@@ -3093,7 +2886,6 @@
         if (fields.empty())
         {
             error(dotLocation, "structure has no fields", "Internal Error");
-            recover();
             indexedExpression = baseExpression;
         }
         else
@@ -3114,7 +2906,6 @@
                     indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
                     if (indexedExpression == 0)
                     {
-                        recover();
                         indexedExpression = baseExpression;
                     }
                     else
@@ -3136,7 +2927,6 @@
             else
             {
                 error(dotLocation, " no such field in structure", fieldString.c_str());
-                recover();
                 indexedExpression = baseExpression;
             }
         }
@@ -3148,7 +2938,6 @@
         if (fields.empty())
         {
             error(dotLocation, "interface block has no fields", "Internal Error");
-            recover();
             indexedExpression = baseExpression;
         }
         else
@@ -3175,7 +2964,6 @@
             else
             {
                 error(dotLocation, " no such field in interface block", fieldString.c_str());
-                recover();
                 indexedExpression = baseExpression;
             }
         }
@@ -3194,7 +2982,6 @@
                   "side",
                   fieldString.c_str());
         }
-        recover();
         indexedExpression = baseExpression;
     }
 
@@ -3239,12 +3026,10 @@
     {
         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
               "location requires an argument");
-        recover();
     }
     else
     {
         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
-        recover();
     }
 
     return qualifier;
@@ -3263,7 +3048,6 @@
     {
         std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
         error(intValueLine, "out of range:", intValueString.c_str(), errorMessage.c_str());
-        recover();
     }
     (*localSize)[index] = intValue;
 }
@@ -3284,7 +3068,6 @@
         {
             error(intValueLine, "out of range:", intValueString.c_str(),
                   "location must be non-negative");
-            recover();
         }
         else
         {
@@ -3309,7 +3092,6 @@
     else
     {
         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
-        recover();
     }
 
     return qualifier;
@@ -3344,7 +3126,6 @@
                 error(rightQualifierLocation,
                       "Cannot have multiple different work group size specifiers",
                       getLocalSizeString(i));
-                recover();
             }
             joinedQualifier.localSize[i] = rightQualifier.localSize[i];
         }
@@ -3401,7 +3182,6 @@
         error(interpolationLoc,
               "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
               getInterpolationString(interpolationQualifier));
-        recover();
 
         mergedQualifier = storageQualifier;
     }
@@ -3414,15 +3194,9 @@
 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
                                                    TFieldList *fieldList)
 {
-    if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
-    {
-        recover();
-    }
+    voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
 
-    if (layoutWorkGroupSizeErrorCheck(typeSpecifier.line, typeSpecifier.layoutQualifier))
-    {
-        recover();
-    }
+    layoutWorkGroupSizeErrorCheck(typeSpecifier.line, typeSpecifier.layoutQualifier);
 
     for (unsigned int i = 0; i < fieldList->size(); ++i)
     {
@@ -3440,8 +3214,7 @@
         // don't allow arrays of arrays
         if (type->isArray())
         {
-            if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
-                recover();
+            arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier);
         }
         if (typeSpecifier.array)
             type->setArraySize(typeSpecifier.arraySize);
@@ -3450,10 +3223,7 @@
             type->setStruct(typeSpecifier.userDef->getStruct());
         }
 
-        if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
-        {
-            recover();
-        }
+        structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]);
     }
 
     return fieldList;
@@ -3474,15 +3244,11 @@
 
     if (!structName->empty())
     {
-        if (reservedErrorCheck(nameLine, *structName))
-        {
-            recover();
-        }
+        reservedErrorCheck(nameLine, *structName);
         TVariable *userTypeDef = new TVariable(structName, *structureType, true);
         if (!symbolTable.declare(userTypeDef))
         {
             error(nameLine, "redefinition", structName->c_str(), "struct");
-            recover();
         }
     }
 
@@ -3499,7 +3265,6 @@
             default:
                 error(field.line(), "invalid qualifier on struct member",
                       getQualifierString(qualifier));
-                recover();
                 break;
         }
     }
@@ -3523,7 +3288,6 @@
     {
         error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
               "switch");
-        recover();
         return nullptr;
     }
 
@@ -3531,7 +3295,6 @@
     {
         if (!ValidateSwitch::validate(switchType, this, statementList, loc))
         {
-            recover();
             return nullptr;
         }
     }
@@ -3540,7 +3303,6 @@
     if (node == nullptr)
     {
         error(loc, "erroneous switch statement", "switch");
-        recover();
         return nullptr;
     }
     return node;
@@ -3551,20 +3313,17 @@
     if (mSwitchNestingLevel == 0)
     {
         error(loc, "case labels need to be inside switch statements", "case");
-        recover();
         return nullptr;
     }
     if (condition == nullptr)
     {
         error(loc, "case label must have a condition", "case");
-        recover();
         return nullptr;
     }
     if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
         condition->isMatrix() || condition->isArray() || condition->isVector())
     {
         error(condition->getLine(), "case label must be a scalar integer", "case");
-        recover();
     }
     TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
     // TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
@@ -3573,13 +3332,11 @@
     if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
     {
         error(condition->getLine(), "case label must be constant", "case");
-        recover();
     }
     TIntermCase *node = intermediate.addCase(condition, loc);
     if (node == nullptr)
     {
         error(loc, "erroneous case statement", "case");
-        recover();
         return nullptr;
     }
     return node;
@@ -3590,14 +3347,12 @@
     if (mSwitchNestingLevel == 0)
     {
         error(loc, "default labels need to be inside switch statements", "default");
-        recover();
         return nullptr;
     }
     TIntermCase *node = intermediate.addCase(nullptr, loc);
     if (node == nullptr)
     {
         error(loc, "erroneous default statement", "default");
-        recover();
         return nullptr;
     }
     return node;
@@ -3654,7 +3409,6 @@
     if (node == nullptr)
     {
         unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
-        recover();
         return child;
     }
     return node;
@@ -3664,8 +3418,7 @@
                                                 TIntermTyped *child,
                                                 const TSourceLoc &loc)
 {
-    if (lValueErrorCheck(loc, GetOperatorString(op), child))
-        recover();
+    lValueErrorCheck(loc, GetOperatorString(op), child);
     return addUnaryMath(op, child, loc);
 }
 
@@ -3858,7 +3611,6 @@
     {
         binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
                       right->getCompleteString());
-        recover();
         return left;
     }
     return node;
@@ -3874,7 +3626,6 @@
     {
         binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
                       right->getCompleteString());
-        recover();
         TConstantUnion *unionArray = new TConstantUnion[1];
         unionArray->setBConst(false);
         return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
@@ -3904,7 +3655,6 @@
     if (node == nullptr)
     {
         assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
-        recover();
         return left;
     }
     return node;
@@ -3924,7 +3674,6 @@
         error(loc,
               "sequence operator is not allowed for void, arrays, or structs containing arrays",
               ",");
-        recover();
     }
 
     return intermediate.addComma(left, right, loc, mShaderVersion);
@@ -3938,21 +3687,18 @@
             if (mLoopNestingLevel <= 0)
             {
                 error(loc, "continue statement only allowed in loops", "");
-                recover();
             }
             break;
         case EOpBreak:
             if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
             {
                 error(loc, "break statement only allowed in loops and switch statements", "");
-                recover();
             }
             break;
         case EOpReturn:
             if (mCurrentFunctionType->getBasicType() != EbtVoid)
             {
                 error(loc, "non-void function must return a value", "return");
-                recover();
             }
             break;
         default:
@@ -3971,12 +3717,10 @@
     if (mCurrentFunctionType->getBasicType() == EbtVoid)
     {
         error(loc, "void function cannot return a value", "return");
-        recover();
     }
     else if (*mCurrentFunctionType != returnValue->getType())
     {
         error(loc, "function return is not matching type:", "return");
-        recover();
     }
     return intermediate.addBranch(op, returnValue, loc);
 }
@@ -4010,7 +3754,6 @@
             TString unmangledName = TFunction::unmangleName(name);
             error(functionCall->getLine(), "Texture offset must be a constant expression",
                   unmangledName.c_str());
-            recover();
         }
         else
         {
@@ -4027,7 +3770,6 @@
                     std::string token = tokenStream.str();
                     error(offset->getLine(), "Texture offset value out of valid range",
                           token.c_str());
-                    recover();
                 }
             }
         }
@@ -4052,17 +3794,14 @@
         if (fnCall->getName() != "length")
         {
             error(loc, "invalid method", fnCall->getName().c_str());
-            recover();
         }
         else if (paramNode != nullptr)
         {
             error(loc, "method takes no parameters", "length");
-            recover();
         }
         else if (typedThis == nullptr || !typedThis->isArray())
         {
             error(loc, "length can only be called on arrays", "length");
-            recover();
         }
         else
         {
@@ -4080,7 +3819,6 @@
                 // length method applied".
                 error(loc, "length can only be called on array names, not on array expressions",
                       "length");
-                recover();
             }
         }
         unionArray->setIConst(arraySize);
@@ -4105,7 +3843,6 @@
 
         if (callNode == nullptr)
         {
-            recover();
             callNode = intermediate.setAggregateOperator(nullptr, op, loc);
         }
         callNode->setType(type);
@@ -4123,10 +3860,9 @@
             //
             // A declared function.
             //
-            if (builtIn && !fnCandidate->getExtension().empty() &&
-                extensionErrorCheck(loc, fnCandidate->getExtension()))
+            if (builtIn && !fnCandidate->getExtension().empty())
             {
-                recover();
+                extensionErrorCheck(loc, fnCandidate->getExtension());
             }
             op = fnCandidate->getBuiltInOp();
             if (builtIn && op != EOpNull)
@@ -4221,7 +3957,6 @@
             unionArray->setFConst(0.0f);
             callNode = intermediate.addConstantUnion(unionArray,
                                                      TType(EbtFloat, EbpUndefined, EvqConst), loc);
-            recover();
         }
     }
     return callNode;
@@ -4232,13 +3967,11 @@
                                                  TIntermTyped *falseBlock,
                                                  const TSourceLoc &loc)
 {
-    if (boolErrorCheck(loc, cond))
-        recover();
+    boolErrorCheck(loc, cond);
 
     if (trueBlock->getType() != falseBlock->getType())
     {
         binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
-        recover();
         return falseBlock;
     }
     // ESSL1 sections 5.2 and 5.7:
@@ -4247,7 +3980,6 @@
     if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
     {
         error(loc, "ternary operator is not allowed for structures or arrays", ":");
-        recover();
         return falseBlock;
     }
     // WebGL2 section 5.26, the following results in an error:
@@ -4255,7 +3987,6 @@
     if (mShaderSpec == SH_WEBGL2_SPEC && trueBlock->getBasicType() == EbtVoid)
     {
         error(loc, "ternary operator is not allowed for void", ":");
-        recover();
         return falseBlock;
     }