LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - ConstantUnion.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 299 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright 2016 The ANGLE Project Authors. All rights reserved.
       3             : // Use of this source code is governed by a BSD-style license that can be
       4             : // found in the LICENSE file.
       5             : //
       6             : // ConstantUnion: Constant folding helper class.
       7             : 
       8             : #include "compiler/translator/ConstantUnion.h"
       9             : 
      10             : #include "common/mathutil.h"
      11             : #include "compiler/translator/Diagnostics.h"
      12             : 
      13             : namespace sh
      14             : {
      15             : 
      16             : namespace
      17             : {
      18             : 
      19           0 : float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
      20             : {
      21           0 :     float result = lhs + rhs;
      22           0 :     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
      23             :     {
      24           0 :         diag->warning(line, "Constant folded undefined addition generated NaN", "+", "");
      25             :     }
      26           0 :     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
      27             :     {
      28           0 :         diag->warning(line, "Constant folded addition overflowed to infinity", "+", "");
      29             :     }
      30           0 :     return result;
      31             : }
      32             : 
      33           0 : float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
      34             : {
      35           0 :     float result = lhs - rhs;
      36           0 :     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
      37             :     {
      38           0 :         diag->warning(line, "Constant folded undefined subtraction generated NaN", "-", "");
      39             :     }
      40           0 :     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
      41             :     {
      42           0 :         diag->warning(line, "Constant folded subtraction overflowed to infinity", "-", "");
      43             :     }
      44           0 :     return result;
      45             : }
      46             : 
      47           0 : float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
      48             : {
      49           0 :     float result = lhs * rhs;
      50           0 :     if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
      51             :     {
      52           0 :         diag->warning(line, "Constant folded undefined multiplication generated NaN", "*", "");
      53             :     }
      54           0 :     else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
      55             :     {
      56           0 :         diag->warning(line, "Constant folded multiplication overflowed to infinity", "*", "");
      57             :     }
      58           0 :     return result;
      59             : }
      60             : 
      61             : }  // anonymous namespace
      62             : 
      63           0 : TConstantUnion::TConstantUnion()
      64             : {
      65           0 :     iConst = 0;
      66           0 :     type   = EbtVoid;
      67           0 : }
      68             : 
      69           0 : bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
      70             : {
      71           0 :     switch (newType)
      72             :     {
      73             :         case EbtFloat:
      74           0 :             switch (constant.type)
      75             :             {
      76             :                 case EbtInt:
      77           0 :                     setFConst(static_cast<float>(constant.getIConst()));
      78           0 :                     break;
      79             :                 case EbtUInt:
      80           0 :                     setFConst(static_cast<float>(constant.getUConst()));
      81           0 :                     break;
      82             :                 case EbtBool:
      83           0 :                     setFConst(static_cast<float>(constant.getBConst()));
      84           0 :                     break;
      85             :                 case EbtFloat:
      86           0 :                     setFConst(static_cast<float>(constant.getFConst()));
      87           0 :                     break;
      88             :                 default:
      89           0 :                     return false;
      90             :             }
      91           0 :             break;
      92             :         case EbtInt:
      93           0 :             switch (constant.type)
      94             :             {
      95             :                 case EbtInt:
      96           0 :                     setIConst(static_cast<int>(constant.getIConst()));
      97           0 :                     break;
      98             :                 case EbtUInt:
      99           0 :                     setIConst(static_cast<int>(constant.getUConst()));
     100           0 :                     break;
     101             :                 case EbtBool:
     102           0 :                     setIConst(static_cast<int>(constant.getBConst()));
     103           0 :                     break;
     104             :                 case EbtFloat:
     105           0 :                     setIConst(static_cast<int>(constant.getFConst()));
     106           0 :                     break;
     107             :                 default:
     108           0 :                     return false;
     109             :             }
     110           0 :             break;
     111             :         case EbtUInt:
     112           0 :             switch (constant.type)
     113             :             {
     114             :                 case EbtInt:
     115           0 :                     setUConst(static_cast<unsigned int>(constant.getIConst()));
     116           0 :                     break;
     117             :                 case EbtUInt:
     118           0 :                     setUConst(static_cast<unsigned int>(constant.getUConst()));
     119           0 :                     break;
     120             :                 case EbtBool:
     121           0 :                     setUConst(static_cast<unsigned int>(constant.getBConst()));
     122           0 :                     break;
     123             :                 case EbtFloat:
     124           0 :                     setUConst(static_cast<unsigned int>(constant.getFConst()));
     125           0 :                     break;
     126             :                 default:
     127           0 :                     return false;
     128             :             }
     129           0 :             break;
     130             :         case EbtBool:
     131           0 :             switch (constant.type)
     132             :             {
     133             :                 case EbtInt:
     134           0 :                     setBConst(constant.getIConst() != 0);
     135           0 :                     break;
     136             :                 case EbtUInt:
     137           0 :                     setBConst(constant.getUConst() != 0);
     138           0 :                     break;
     139             :                 case EbtBool:
     140           0 :                     setBConst(constant.getBConst());
     141           0 :                     break;
     142             :                 case EbtFloat:
     143           0 :                     setBConst(constant.getFConst() != 0.0f);
     144           0 :                     break;
     145             :                 default:
     146           0 :                     return false;
     147             :             }
     148           0 :             break;
     149             :         case EbtStruct:  // Struct fields don't get cast
     150           0 :             switch (constant.type)
     151             :             {
     152             :                 case EbtInt:
     153           0 :                     setIConst(constant.getIConst());
     154           0 :                     break;
     155             :                 case EbtUInt:
     156           0 :                     setUConst(constant.getUConst());
     157           0 :                     break;
     158             :                 case EbtBool:
     159           0 :                     setBConst(constant.getBConst());
     160           0 :                     break;
     161             :                 case EbtFloat:
     162           0 :                     setFConst(constant.getFConst());
     163           0 :                     break;
     164             :                 default:
     165           0 :                     return false;
     166             :             }
     167           0 :             break;
     168             :         default:
     169           0 :             return false;
     170             :     }
     171             : 
     172           0 :     return true;
     173             : }
     174             : 
     175           0 : bool TConstantUnion::operator==(const int i) const
     176             : {
     177           0 :     return i == iConst;
     178             : }
     179             : 
     180           0 : bool TConstantUnion::operator==(const unsigned int u) const
     181             : {
     182           0 :     return u == uConst;
     183             : }
     184             : 
     185           0 : bool TConstantUnion::operator==(const float f) const
     186             : {
     187           0 :     return f == fConst;
     188             : }
     189             : 
     190           0 : bool TConstantUnion::operator==(const bool b) const
     191             : {
     192           0 :     return b == bConst;
     193             : }
     194             : 
     195           0 : bool TConstantUnion::operator==(const TConstantUnion &constant) const
     196             : {
     197           0 :     if (constant.type != type)
     198           0 :         return false;
     199             : 
     200           0 :     switch (type)
     201             :     {
     202             :         case EbtInt:
     203           0 :             return constant.iConst == iConst;
     204             :         case EbtUInt:
     205           0 :             return constant.uConst == uConst;
     206             :         case EbtFloat:
     207           0 :             return constant.fConst == fConst;
     208             :         case EbtBool:
     209           0 :             return constant.bConst == bConst;
     210             :         default:
     211           0 :             return false;
     212             :     }
     213             : }
     214             : 
     215           0 : bool TConstantUnion::operator!=(const int i) const
     216             : {
     217           0 :     return !operator==(i);
     218             : }
     219             : 
     220           0 : bool TConstantUnion::operator!=(const unsigned int u) const
     221             : {
     222           0 :     return !operator==(u);
     223             : }
     224             : 
     225           0 : bool TConstantUnion::operator!=(const float f) const
     226             : {
     227           0 :     return !operator==(f);
     228             : }
     229             : 
     230           0 : bool TConstantUnion::operator!=(const bool b) const
     231             : {
     232           0 :     return !operator==(b);
     233             : }
     234             : 
     235           0 : bool TConstantUnion::operator!=(const TConstantUnion &constant) const
     236             : {
     237           0 :     return !operator==(constant);
     238             : }
     239             : 
     240           0 : bool TConstantUnion::operator>(const TConstantUnion &constant) const
     241             : {
     242           0 :     ASSERT(type == constant.type);
     243           0 :     switch (type)
     244             :     {
     245             :         case EbtInt:
     246           0 :             return iConst > constant.iConst;
     247             :         case EbtUInt:
     248           0 :             return uConst > constant.uConst;
     249             :         case EbtFloat:
     250           0 :             return fConst > constant.fConst;
     251             :         default:
     252           0 :             return false;  // Invalid operation, handled at semantic analysis
     253             :     }
     254             : }
     255             : 
     256           0 : bool TConstantUnion::operator<(const TConstantUnion &constant) const
     257             : {
     258           0 :     ASSERT(type == constant.type);
     259           0 :     switch (type)
     260             :     {
     261             :         case EbtInt:
     262           0 :             return iConst < constant.iConst;
     263             :         case EbtUInt:
     264           0 :             return uConst < constant.uConst;
     265             :         case EbtFloat:
     266           0 :             return fConst < constant.fConst;
     267             :         default:
     268           0 :             return false;  // Invalid operation, handled at semantic analysis
     269             :     }
     270             : }
     271             : 
     272             : // static
     273           0 : TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
     274             :                                    const TConstantUnion &rhs,
     275             :                                    TDiagnostics *diag,
     276             :                                    const TSourceLoc &line)
     277             : {
     278           0 :     TConstantUnion returnValue;
     279           0 :     ASSERT(lhs.type == rhs.type);
     280           0 :     switch (lhs.type)
     281             :     {
     282             :         case EbtInt:
     283           0 :             returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
     284           0 :             break;
     285             :         case EbtUInt:
     286           0 :             returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
     287           0 :             break;
     288             :         case EbtFloat:
     289           0 :             returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
     290           0 :             break;
     291             :         default:
     292           0 :             UNREACHABLE();
     293             :     }
     294             : 
     295           0 :     return returnValue;
     296             : }
     297             : 
     298             : // static
     299           0 : TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
     300             :                                    const TConstantUnion &rhs,
     301             :                                    TDiagnostics *diag,
     302             :                                    const TSourceLoc &line)
     303             : {
     304           0 :     TConstantUnion returnValue;
     305           0 :     ASSERT(lhs.type == rhs.type);
     306           0 :     switch (lhs.type)
     307             :     {
     308             :         case EbtInt:
     309           0 :             returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
     310           0 :             break;
     311             :         case EbtUInt:
     312           0 :             returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
     313           0 :             break;
     314             :         case EbtFloat:
     315           0 :             returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
     316           0 :             break;
     317             :         default:
     318           0 :             UNREACHABLE();
     319             :     }
     320             : 
     321           0 :     return returnValue;
     322             : }
     323             : 
     324             : // static
     325           0 : TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
     326             :                                    const TConstantUnion &rhs,
     327             :                                    TDiagnostics *diag,
     328             :                                    const TSourceLoc &line)
     329             : {
     330           0 :     TConstantUnion returnValue;
     331           0 :     ASSERT(lhs.type == rhs.type);
     332           0 :     switch (lhs.type)
     333             :     {
     334             :         case EbtInt:
     335           0 :             returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
     336           0 :             break;
     337             :         case EbtUInt:
     338             :             // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that
     339             :             // to implement wrapping multiplication.
     340           0 :             returnValue.setUConst(lhs.uConst * rhs.uConst);
     341           0 :             break;
     342             :         case EbtFloat:
     343           0 :             returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line));
     344           0 :             break;
     345             :         default:
     346           0 :             UNREACHABLE();
     347             :     }
     348             : 
     349           0 :     return returnValue;
     350             : }
     351             : 
     352           0 : TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
     353             : {
     354           0 :     TConstantUnion returnValue;
     355           0 :     ASSERT(type == constant.type);
     356           0 :     switch (type)
     357             :     {
     358             :         case EbtInt:
     359           0 :             returnValue.setIConst(iConst % constant.iConst);
     360           0 :             break;
     361             :         case EbtUInt:
     362           0 :             returnValue.setUConst(uConst % constant.uConst);
     363           0 :             break;
     364             :         default:
     365           0 :             UNREACHABLE();
     366             :     }
     367             : 
     368           0 :     return returnValue;
     369             : }
     370             : 
     371             : // static
     372           0 : TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
     373             :                                       const TConstantUnion &rhs,
     374             :                                       TDiagnostics *diag,
     375             :                                       const TSourceLoc &line)
     376             : {
     377           0 :     TConstantUnion returnValue;
     378           0 :     ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
     379           0 :     ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
     380           0 :     if ((rhs.type == EbtInt && (rhs.iConst < 0 || rhs.iConst > 31)) ||
     381           0 :         (rhs.type == EbtUInt && rhs.uConst > 31u))
     382             :     {
     383           0 :         diag->error(line, "Undefined shift (operand out of range)", ">>", "");
     384           0 :         switch (lhs.type)
     385             :         {
     386             :             case EbtInt:
     387           0 :                 returnValue.setIConst(0);
     388           0 :                 break;
     389             :             case EbtUInt:
     390           0 :                 returnValue.setUConst(0u);
     391           0 :                 break;
     392             :             default:
     393           0 :                 UNREACHABLE();
     394             :         }
     395           0 :         return returnValue;
     396             :     }
     397             : 
     398           0 :     switch (lhs.type)
     399             :     {
     400             :         case EbtInt:
     401             :         {
     402           0 :             unsigned int shiftOffset = 0;
     403           0 :             switch (rhs.type)
     404             :             {
     405             :                 case EbtInt:
     406           0 :                     shiftOffset = static_cast<unsigned int>(rhs.iConst);
     407           0 :                     break;
     408             :                 case EbtUInt:
     409           0 :                     shiftOffset = rhs.uConst;
     410           0 :                     break;
     411             :                 default:
     412           0 :                     UNREACHABLE();
     413             :             }
     414           0 :             if (shiftOffset > 0)
     415             :             {
     416             :                 // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
     417             :                 // the sign bit." In C++ shifting negative integers is undefined, so we implement
     418             :                 // extending the sign bit manually.
     419           0 :                 int lhsSafe        = lhs.iConst;
     420           0 :                 if (lhsSafe == std::numeric_limits<int>::min())
     421             :                 {
     422             :                     // The min integer needs special treatment because only bit it has set is the
     423             :                     // sign bit, which we clear later to implement safe right shift of negative
     424             :                     // numbers.
     425           0 :                     lhsSafe = -0x40000000;
     426           0 :                     --shiftOffset;
     427             :                 }
     428           0 :                 if (shiftOffset > 0)
     429             :                 {
     430           0 :                     bool extendSignBit = false;
     431           0 :                     if (lhsSafe < 0)
     432             :                     {
     433           0 :                         extendSignBit = true;
     434             :                         // Clear the sign bit so that bitshift right is defined in C++.
     435           0 :                         lhsSafe &= 0x7fffffff;
     436           0 :                         ASSERT(lhsSafe > 0);
     437             :                     }
     438           0 :                     returnValue.setIConst(lhsSafe >> shiftOffset);
     439             : 
     440             :                     // Manually fill in the extended sign bit if necessary.
     441           0 :                     if (extendSignBit)
     442             :                     {
     443           0 :                         int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
     444           0 :                         returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
     445             :                     }
     446             :                 }
     447             :                 else
     448             :                 {
     449           0 :                     returnValue.setIConst(lhsSafe);
     450             :                 }
     451             :             }
     452             :             else
     453             :             {
     454           0 :                 returnValue.setIConst(lhs.iConst);
     455             :             }
     456           0 :             break;
     457             :         }
     458             :         case EbtUInt:
     459           0 :             switch (rhs.type)
     460             :             {
     461             :                 case EbtInt:
     462           0 :                     returnValue.setUConst(lhs.uConst >> rhs.iConst);
     463           0 :                     break;
     464             :                 case EbtUInt:
     465           0 :                     returnValue.setUConst(lhs.uConst >> rhs.uConst);
     466           0 :                     break;
     467             :                 default:
     468           0 :                     UNREACHABLE();
     469             :             }
     470           0 :             break;
     471             : 
     472             :         default:
     473           0 :             UNREACHABLE();
     474             :     }
     475           0 :     return returnValue;
     476             : }
     477             : 
     478             : // static
     479           0 : TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
     480             :                                       const TConstantUnion &rhs,
     481             :                                       TDiagnostics *diag,
     482             :                                       const TSourceLoc &line)
     483             : {
     484           0 :     TConstantUnion returnValue;
     485           0 :     ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
     486           0 :     ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
     487           0 :     if ((rhs.type == EbtInt && (rhs.iConst < 0 || rhs.iConst > 31)) ||
     488           0 :         (rhs.type == EbtUInt && rhs.uConst > 31u))
     489             :     {
     490           0 :         diag->error(line, "Undefined shift (operand out of range)", "<<", "");
     491           0 :         switch (lhs.type)
     492             :         {
     493             :             case EbtInt:
     494           0 :                 returnValue.setIConst(0);
     495           0 :                 break;
     496             :             case EbtUInt:
     497           0 :                 returnValue.setUConst(0u);
     498           0 :                 break;
     499             :             default:
     500           0 :                 UNREACHABLE();
     501             :         }
     502           0 :         return returnValue;
     503             :     }
     504             : 
     505           0 :     switch (lhs.type)
     506             :     {
     507             :         case EbtInt:
     508           0 :             switch (rhs.type)
     509             :             {
     510             :                 // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
     511             :                 // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
     512             :                 // integer overflow or undefined shift of a negative integer.
     513             :                 case EbtInt:
     514           0 :                     returnValue.setIConst(
     515           0 :                         static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
     516           0 :                     break;
     517             :                 case EbtUInt:
     518           0 :                     returnValue.setIConst(
     519           0 :                         static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
     520           0 :                     break;
     521             :                 default:
     522           0 :                     UNREACHABLE();
     523             :             }
     524           0 :             break;
     525             : 
     526             :         case EbtUInt:
     527           0 :             switch (rhs.type)
     528             :             {
     529             :                 case EbtInt:
     530           0 :                     returnValue.setUConst(lhs.uConst << rhs.iConst);
     531           0 :                     break;
     532             :                 case EbtUInt:
     533           0 :                     returnValue.setUConst(lhs.uConst << rhs.uConst);
     534           0 :                     break;
     535             :                 default:
     536           0 :                     UNREACHABLE();
     537             :             }
     538           0 :             break;
     539             : 
     540             :         default:
     541           0 :             UNREACHABLE();
     542             :     }
     543           0 :     return returnValue;
     544             : }
     545             : 
     546           0 : TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
     547             : {
     548           0 :     TConstantUnion returnValue;
     549           0 :     ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
     550           0 :     switch (type)
     551             :     {
     552             :         case EbtInt:
     553           0 :             returnValue.setIConst(iConst & constant.iConst);
     554           0 :             break;
     555             :         case EbtUInt:
     556           0 :             returnValue.setUConst(uConst & constant.uConst);
     557           0 :             break;
     558             :         default:
     559           0 :             UNREACHABLE();
     560             :     }
     561             : 
     562           0 :     return returnValue;
     563             : }
     564             : 
     565           0 : TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
     566             : {
     567           0 :     TConstantUnion returnValue;
     568           0 :     ASSERT(type == constant.type);
     569           0 :     switch (type)
     570             :     {
     571             :         case EbtInt:
     572           0 :             returnValue.setIConst(iConst | constant.iConst);
     573           0 :             break;
     574             :         case EbtUInt:
     575           0 :             returnValue.setUConst(uConst | constant.uConst);
     576           0 :             break;
     577             :         default:
     578           0 :             UNREACHABLE();
     579             :     }
     580             : 
     581           0 :     return returnValue;
     582             : }
     583             : 
     584           0 : TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
     585             : {
     586           0 :     TConstantUnion returnValue;
     587           0 :     ASSERT(type == constant.type);
     588           0 :     switch (type)
     589             :     {
     590             :         case EbtInt:
     591           0 :             returnValue.setIConst(iConst ^ constant.iConst);
     592           0 :             break;
     593             :         case EbtUInt:
     594           0 :             returnValue.setUConst(uConst ^ constant.uConst);
     595           0 :             break;
     596             :         default:
     597           0 :             UNREACHABLE();
     598             :     }
     599             : 
     600           0 :     return returnValue;
     601             : }
     602             : 
     603           0 : TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
     604             : {
     605           0 :     TConstantUnion returnValue;
     606           0 :     ASSERT(type == constant.type);
     607           0 :     switch (type)
     608             :     {
     609             :         case EbtBool:
     610           0 :             returnValue.setBConst(bConst && constant.bConst);
     611           0 :             break;
     612             :         default:
     613           0 :             UNREACHABLE();
     614             :     }
     615             : 
     616           0 :     return returnValue;
     617             : }
     618             : 
     619           0 : TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
     620             : {
     621           0 :     TConstantUnion returnValue;
     622           0 :     ASSERT(type == constant.type);
     623           0 :     switch (type)
     624             :     {
     625             :         case EbtBool:
     626           0 :             returnValue.setBConst(bConst || constant.bConst);
     627           0 :             break;
     628             :         default:
     629           0 :             UNREACHABLE();
     630             :     }
     631             : 
     632           0 :     return returnValue;
     633             : }
     634             : 
     635             : }  // namespace sh

Generated by: LCOV version 1.13