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// The SeparateDeclarations function processes declarations, so that in the end each declaration
7// contains only one declarator.
8// This is useful as an intermediate step when initialization needs to be separated from
9// declaration, or when things need to be unfolded out of the initializer.
10// Example:
11// int a[1] = int[1](1), b[1] = int[1](2);
12// gets transformed when run through this class into the AST equivalent of:
13// int a[1] = int[1](1);
14// int b[1] = int[1](2);
15
16#include "compiler/translator/tree_ops/SeparateDeclarations.h"
17
18#include "compiler/translator/tree_util/IntermTraverse.h"
19
20namespace sh
21{
22
23namespace
24{
25
26class SeparateDeclarationsTraverser : private TIntermTraverser
27{
28 public:
29 static void apply(TIntermNode *root);
30
31 private:
32 SeparateDeclarationsTraverser();
33 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
34};
35
36void SeparateDeclarationsTraverser::apply(TIntermNode *root)
37{
38 SeparateDeclarationsTraverser separateDecl;
39 root->traverse(&separateDecl);
40 separateDecl.updateTree();
41}
42
43SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
44 : TIntermTraverser(true, false, false)
45{}
46
47bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
48{
49 TIntermSequence *sequence = node->getSequence();
50 if (sequence->size() > 1)
51 {
52 TIntermBlock *parentBlock = getParentNode()->getAsBlock();
53 ASSERT(parentBlock != nullptr);
54
55 TIntermSequence replacementDeclarations;
56 for (size_t ii = 0; ii < sequence->size(); ++ii)
57 {
58 TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
59
60 replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
61 replacementDeclaration->setLine(sequence->at(ii)->getLine());
62 replacementDeclarations.push_back(replacementDeclaration);
63 }
64
65 mMultiReplacements.push_back(
66 NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
67 }
68 return false;
69}
70
71} // namespace
72
73void SeparateDeclarations(TIntermNode *root)
74{
75 SeparateDeclarationsTraverser::apply(root);
76}
77
78} // namespace sh
79