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

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2015 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             : 
       7             : #include "compiler/translator/ValidateSwitch.h"
       8             : 
       9             : #include "compiler/translator/ParseContext.h"
      10             : 
      11             : namespace sh
      12             : {
      13             : 
      14           0 : bool ValidateSwitch::validate(TBasicType switchType,
      15             :                               TParseContext *context,
      16             :                               TIntermBlock *statementList,
      17             :                               const TSourceLoc &loc)
      18             : {
      19           0 :     ValidateSwitch validate(switchType, context);
      20           0 :     ASSERT(statementList);
      21           0 :     statementList->traverse(&validate);
      22           0 :     return validate.validateInternal(loc);
      23             : }
      24             : 
      25           0 : ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context)
      26             :     : TIntermTraverser(true, false, true),
      27             :       mSwitchType(switchType),
      28             :       mContext(context),
      29             :       mCaseTypeMismatch(false),
      30             :       mFirstCaseFound(false),
      31             :       mStatementBeforeCase(false),
      32             :       mLastStatementWasCase(false),
      33             :       mControlFlowDepth(0),
      34             :       mCaseInsideControlFlow(false),
      35             :       mDefaultCount(0),
      36           0 :       mDuplicateCases(false)
      37           0 : {}
      38             : 
      39           0 : void ValidateSwitch::visitSymbol(TIntermSymbol *)
      40             : {
      41           0 :     if (!mFirstCaseFound)
      42           0 :         mStatementBeforeCase = true;
      43           0 :     mLastStatementWasCase = false;
      44           0 : }
      45             : 
      46           0 : void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *)
      47             : {
      48             :     // Conditions of case labels are not traversed, so this is some other constant
      49             :     // Could be just a statement like "0;"
      50           0 :     if (!mFirstCaseFound)
      51           0 :         mStatementBeforeCase = true;
      52           0 :     mLastStatementWasCase = false;
      53           0 : }
      54             : 
      55           0 : bool ValidateSwitch::visitBinary(Visit, TIntermBinary *)
      56             : {
      57           0 :     if (!mFirstCaseFound)
      58           0 :         mStatementBeforeCase = true;
      59           0 :     mLastStatementWasCase = false;
      60           0 :     return true;
      61             : }
      62             : 
      63           0 : bool ValidateSwitch::visitUnary(Visit, TIntermUnary *)
      64             : {
      65           0 :     if (!mFirstCaseFound)
      66           0 :         mStatementBeforeCase = true;
      67           0 :     mLastStatementWasCase    = false;
      68           0 :     return true;
      69             : }
      70             : 
      71           0 : bool ValidateSwitch::visitTernary(Visit, TIntermTernary *)
      72             : {
      73           0 :     if (!mFirstCaseFound)
      74           0 :         mStatementBeforeCase = true;
      75           0 :     mLastStatementWasCase = false;
      76           0 :     return true;
      77             : }
      78             : 
      79           0 : bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *)
      80             : {
      81           0 :     if (visit == PreVisit)
      82           0 :         ++mControlFlowDepth;
      83           0 :     if (visit == PostVisit)
      84           0 :         --mControlFlowDepth;
      85           0 :     if (!mFirstCaseFound)
      86           0 :         mStatementBeforeCase = true;
      87           0 :     mLastStatementWasCase = false;
      88           0 :     return true;
      89             : }
      90             : 
      91           0 : bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *)
      92             : {
      93           0 :     if (!mFirstCaseFound)
      94           0 :         mStatementBeforeCase = true;
      95           0 :     mLastStatementWasCase = false;
      96             :     // Don't go into nested switch statements
      97           0 :     return false;
      98             : }
      99             : 
     100           0 : bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
     101             : {
     102           0 :     const char *nodeStr = node->hasCondition() ? "case" : "default";
     103           0 :     if (mControlFlowDepth > 0)
     104             :     {
     105           0 :         mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr);
     106           0 :         mCaseInsideControlFlow = true;
     107             :     }
     108           0 :     mFirstCaseFound = true;
     109           0 :     mLastStatementWasCase = true;
     110           0 :     if (!node->hasCondition())
     111             :     {
     112           0 :         ++mDefaultCount;
     113           0 :         if (mDefaultCount > 1)
     114             :         {
     115           0 :             mContext->error(node->getLine(), "duplicate default label", nodeStr);
     116             :         }
     117             :     }
     118             :     else
     119             :     {
     120           0 :         TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion();
     121           0 :         if (condition == nullptr)
     122             :         {
     123             :             // This can happen in error cases.
     124           0 :             return false;
     125             :         }
     126           0 :         TBasicType conditionType = condition->getBasicType();
     127           0 :         if (conditionType != mSwitchType)
     128             :         {
     129           0 :             mContext->error(condition->getLine(),
     130           0 :                 "case label type does not match switch init-expression type", nodeStr);
     131           0 :             mCaseTypeMismatch = true;
     132             :         }
     133             : 
     134           0 :         if (conditionType == EbtInt)
     135             :         {
     136           0 :             int iConst = condition->getIConst(0);
     137           0 :             if (mCasesSigned.find(iConst) != mCasesSigned.end())
     138             :             {
     139           0 :                 mContext->error(condition->getLine(), "duplicate case label", nodeStr);
     140           0 :                 mDuplicateCases = true;
     141             :             }
     142             :             else
     143             :             {
     144           0 :                 mCasesSigned.insert(iConst);
     145             :             }
     146             :         }
     147           0 :         else if (conditionType == EbtUInt)
     148             :         {
     149           0 :             unsigned int uConst = condition->getUConst(0);
     150           0 :             if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end())
     151             :             {
     152           0 :                 mContext->error(condition->getLine(), "duplicate case label", nodeStr);
     153           0 :                 mDuplicateCases = true;
     154             :             }
     155             :             else
     156             :             {
     157           0 :                 mCasesUnsigned.insert(uConst);
     158             :             }
     159             :         }
     160             :         // Other types are possible only in error cases, where the error has already been generated
     161             :         // when parsing the case statement.
     162             :     }
     163             :     // Don't traverse the condition of the case statement
     164           0 :     return false;
     165             : }
     166             : 
     167           0 : bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *)
     168             : {
     169           0 :     if (getParentNode() != nullptr)
     170             :     {
     171             :         // This is not the statementList node, but some other node.
     172           0 :         if (!mFirstCaseFound)
     173           0 :             mStatementBeforeCase = true;
     174           0 :         mLastStatementWasCase = false;
     175             :     }
     176           0 :     return true;
     177             : }
     178             : 
     179           0 : bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *)
     180             : {
     181           0 :     if (visit == PreVisit)
     182           0 :         ++mControlFlowDepth;
     183           0 :     if (visit == PostVisit)
     184           0 :         --mControlFlowDepth;
     185           0 :     if (!mFirstCaseFound)
     186           0 :         mStatementBeforeCase = true;
     187           0 :     mLastStatementWasCase = false;
     188           0 :     return true;
     189             : }
     190             : 
     191           0 : bool ValidateSwitch::visitBranch(Visit, TIntermBranch *)
     192             : {
     193           0 :     if (!mFirstCaseFound)
     194           0 :         mStatementBeforeCase = true;
     195           0 :     mLastStatementWasCase = false;
     196           0 :     return true;
     197             : }
     198             : 
     199           0 : bool ValidateSwitch::validateInternal(const TSourceLoc &loc)
     200             : {
     201           0 :     if (mStatementBeforeCase)
     202             :     {
     203           0 :         mContext->error(loc,
     204           0 :             "statement before the first label", "switch");
     205             :     }
     206           0 :     if (mLastStatementWasCase)
     207             :     {
     208           0 :         mContext->error(loc,
     209           0 :             "no statement between the last label and the end of the switch statement", "switch");
     210             :     }
     211           0 :     return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow &&
     212           0 :         !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
     213             : }
     214             : 
     215             : }  // namespace sh

Generated by: LCOV version 1.13