| // |
| // Copyright (c) 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a |
| // return. |
| // |
| |
| #include "compiler/translator/AddDefaultReturnStatements.h" |
| |
| #include "compiler/translator/IntermNode.h" |
| #include "compiler/translator/util.h" |
| |
| namespace sh |
| { |
| |
| namespace |
| { |
| |
| class AddDefaultReturnStatementsTraverser : private TIntermTraverser |
| { |
| public: |
| static void Apply(TIntermNode *root) |
| { |
| AddDefaultReturnStatementsTraverser separateInit; |
| root->traverse(&separateInit); |
| separateInit.updateTree(); |
| } |
| |
| private: |
| AddDefaultReturnStatementsTraverser() : TIntermTraverser(true, false, false) {} |
| |
| static bool IsFunctionWithoutReturnStatement(TIntermFunctionDefinition *node, TType *returnType) |
| { |
| *returnType = node->getType(); |
| if (node->getType().getBasicType() == EbtVoid) |
| { |
| return false; |
| } |
| |
| TIntermBlock *bodyNode = node->getBody(); |
| TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode(); |
| if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *node) override |
| { |
| TType returnType; |
| if (IsFunctionWithoutReturnStatement(node, &returnType)) |
| { |
| TIntermBranch *branch = |
| new TIntermBranch(EOpReturn, TIntermTyped::CreateZero(returnType)); |
| |
| TIntermBlock *bodyNode = node->getBody(); |
| bodyNode->getSequence()->push_back(branch); |
| |
| return false; |
| } |
| |
| return true; |
| } |
| }; |
| } // anonymous namespace |
| |
| void AddDefaultReturnStatements(TIntermNode *node) |
| { |
| AddDefaultReturnStatementsTraverser::Apply(node); |
| } |
| |
| } // namespace sh |