glslang: Fix over 100 warnings from MSVC warning level 4.
[platform/upstream/glslang.git] / glslang / MachineIndependent / limits.cpp
1 //\r
2 //Copyright (C) 2013 LunarG, Inc.\r
3 //\r
4 //All rights reserved.\r
5 //\r
6 //Redistribution and use in source and binary forms, with or without\r
7 //modification, are permitted provided that the following conditions\r
8 //are met:\r
9 //\r
10 //    Redistributions of source code must retain the above copyright\r
11 //    notice, this list of conditions and the following disclaimer.\r
12 //\r
13 //    Redistributions in binary form must reproduce the above\r
14 //    copyright notice, this list of conditions and the following\r
15 //    disclaimer in the documentation and/or other materials provided\r
16 //    with the distribution.\r
17 //\r
18 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its\r
19 //    contributors may be used to endorse or promote products derived\r
20 //    from this software without specific prior written permission.\r
21 //\r
22 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
23 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
24 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
25 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
26 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
27 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
28 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
29 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
30 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
31 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
32 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
33 //POSSIBILITY OF SUCH DAMAGE.\r
34 //\r
35 \r
36 //\r
37 // Do sub tree walks for\r
38 // 1) inductive loop bodies to see if the inductive variable is modified\r
39 // 2) array-index expressions to see if they are "constant-index-expression"\r
40 //\r
41 // These are per Appendix A of ES 2.0:\r
42 //\r
43 // "Within the body of the loop, the loop index is not statically assigned to nor is it used as the\r
44 // argument to a function out or inout parameter."\r
45 //\r
46 // "The following are constant-index-expressions:\r
47 //  - Constant expressions\r
48 //  - Loop indices as defined in section 4\r
49 //  - Expressions composed of both of the above"\r
50 //\r
51 // N.B.: assuming the last rule excludes function calls\r
52 //\r
53 \r
54 #include "ParseHelper.h"\r
55 \r
56 namespace glslang {\r
57 \r
58 //\r
59 // The inductive loop-body traverser.\r
60 //\r
61 // Just look at things that might modify the loop index.\r
62 //\r
63 \r
64 class TInductiveTraverser : public TIntermTraverser {\r
65 public:\r
66     TInductiveTraverser(int id, TSymbolTable& st)\r
67     : loopId(id), symbolTable(st), bad(false)  { }\r
68 \r
69     virtual bool visitBinary(TVisit, TIntermBinary* node);\r
70     virtual bool visitUnary(TVisit, TIntermUnary* node);\r
71     virtual bool visitAggregate(TVisit, TIntermAggregate* node);\r
72 \r
73     int loopId;           // unique ID of the symbol that's the loop inductive variable\r
74     TSymbolTable& symbolTable;\r
75     bool bad;\r
76     TSourceLoc badLoc;\r
77 \r
78 protected:\r
79     TInductiveTraverser(TInductiveTraverser&);\r
80     TInductiveTraverser& operator=(TInductiveTraverser&);\r
81 };\r
82 \r
83 // check binary operations for those modifying the loop index\r
84 bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)\r
85 {\r
86     if (node->modifiesState() && node->getLeft()->getAsSymbolNode() && \r
87                                  node->getLeft()->getAsSymbolNode()->getId() == loopId) {\r
88         bad = true;\r
89         badLoc = node->getLoc();\r
90     }\r
91 \r
92     return true;\r
93 }\r
94 \r
95 // check unary operations for those modifying the loop index\r
96 bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)\r
97 {\r
98     if (node->modifiesState() && node->getOperand()->getAsSymbolNode() && \r
99                                  node->getOperand()->getAsSymbolNode()->getId() == loopId) {\r
100         bad = true;\r
101         badLoc = node->getLoc();\r
102     }\r
103 \r
104     return true;\r
105 }\r
106 \r
107 // check function calls for arguments modifying the loop index\r
108 bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)\r
109 {\r
110     if (node->getOp() == EOpFunctionCall) {\r
111         // see if an out or inout argument is the loop index\r
112         const TIntermSequence& args = node->getSequence();\r
113         for (int i = 0; i < (int)args.size(); ++i) {\r
114             if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) {\r
115                 TSymbol* function = symbolTable.find(node->getName());\r
116                 const TType* type = (*function->getAsFunction())[i].type;\r
117                 if (type->getQualifier().storage == EvqOut ||\r
118                     type->getQualifier().storage == EvqInOut) {\r
119                     bad = true;\r
120                     badLoc = node->getLoc();\r
121                 }\r
122             }\r
123         }\r
124     }\r
125 \r
126     return true;\r
127 }\r
128 \r
129 //\r
130 // External function to call for loop check.\r
131 //\r
132 void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)\r
133 {\r
134     TInductiveTraverser it(loopId, symbolTable);\r
135 \r
136     if (! body)\r
137         return;\r
138 \r
139     body->traverse(&it);\r
140 \r
141     if (it.bad)\r
142         error(it.badLoc, "inductive loop index modified", "limitations", "");\r
143 }\r
144 \r
145 //\r
146 // The "constant-index-expression" tranverser.\r
147 //\r
148 // Just look at things that can form an index.  \r
149 //\r
150 \r
151 class TIndexTraverser : public TIntermTraverser {\r
152 public:\r
153     TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }\r
154     virtual void visitSymbol(TIntermSymbol* symbol);\r
155     virtual bool visitAggregate(TVisit, TIntermAggregate* node);\r
156     const TIdSetType& inductiveLoopIds;\r
157     bool bad;\r
158     TSourceLoc badLoc;\r
159 \r
160 protected:\r
161     TIndexTraverser(TIndexTraverser&);\r
162     TIndexTraverser& operator=(TIndexTraverser&);\r
163 };\r
164 \r
165 // make sure symbols are inductive-loop indexes\r
166 void TIndexTraverser::visitSymbol(TIntermSymbol* symbol)\r
167 {\r
168     if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) {\r
169         bad = true;\r
170         badLoc = symbol->getLoc();\r
171     }\r
172 }\r
173 \r
174 // check for function calls, assuming they are bad; spec. doesn't really say\r
175 bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)\r
176 {\r
177     if (node->getOp() == EOpFunctionCall) {\r
178         bad = true;\r
179         badLoc = node->getLoc();\r
180     }\r
181 \r
182     return true;\r
183 }\r
184 \r
185 //\r
186 // External function to call for loop check.\r
187 //\r
188 void TParseContext::constantIndexExpressionCheck(TIntermNode* index)\r
189 {\r
190     TIndexTraverser it(inductiveLoopIds);\r
191 \r
192     index->traverse(&it);\r
193 \r
194     if (it.bad)\r
195         error(it.badLoc, "Non-constant-index-expression", "limitations", "");\r
196 }\r
197 \r
198 } // end namespace glslang\r