Fix variable scoping of do-while
[platform/upstream/glslang.git] / glslang / MachineIndependent / ParseHelper.h
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2013 LunarG, Inc.
4 // Copyright (C) 2015-2018 Google, Inc.
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 //    Redistributions of source code must retain the above copyright
13 //    notice, this list of conditions and the following disclaimer.
14 //
15 //    Redistributions in binary form must reproduce the above
16 //    copyright notice, this list of conditions and the following
17 //    disclaimer in the documentation and/or other materials provided
18 //    with the distribution.
19 //
20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 //    contributors may be used to endorse or promote products derived
22 //    from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37
38 //
39 // This header defines a two-level parse-helper hierarchy, derived from
40 // TParseVersions:
41 //  - TParseContextBase:  sharable across multiple parsers
42 //  - TParseContext:      GLSL specific helper
43 //
44
45 #ifndef _PARSER_HELPER_INCLUDED_
46 #define _PARSER_HELPER_INCLUDED_
47
48 #include <cstdarg>
49 #include <functional>
50
51 #include "parseVersions.h"
52 #include "../Include/ShHandle.h"
53 #include "SymbolTable.h"
54 #include "localintermediate.h"
55 #include "Scan.h"
56 #include "attribute.h"
57
58 namespace glslang {
59
60 struct TPragma {
61     TPragma(bool o, bool d) : optimize(o), debug(d) { }
62     bool optimize;
63     bool debug;
64     TPragmaTable pragmaTable;
65 };
66
67 class TScanContext;
68 class TPpContext;
69
70 typedef std::set<long long> TIdSetType;
71 typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
72
73 //
74 // Sharable code (as well as what's in TParseVersions) across
75 // parse helpers.
76 //
77 class TParseContextBase : public TParseVersions {
78 public:
79     TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
80                       EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
81                       TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
82                       const TString* entryPoint = nullptr)
83           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
84             scopeMangler("::"),
85             symbolTable(symbolTable),
86             statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
87             currentFunctionType(nullptr),
88             postEntryPointReturn(false),
89             contextPragma(true, false),
90             beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
91             parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
92             limits(resources.limits),
93             globalUniformBlock(nullptr),
94             globalUniformBinding(TQualifier::layoutBindingEnd),
95             globalUniformSet(TQualifier::layoutSetEnd),
96             atomicCounterBlockSet(TQualifier::layoutSetEnd)
97     {
98         if (entryPoint != nullptr)
99             sourceEntryPointName = *entryPoint;
100     }
101     virtual ~TParseContextBase() { }
102
103 #if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
104     virtual void C_DECL   error(const TSourceLoc&, const char* szReason, const char* szToken,
105                                 const char* szExtraInfoFormat, ...);
106     virtual void C_DECL    warn(const TSourceLoc&, const char* szReason, const char* szToken,
107                                 const char* szExtraInfoFormat, ...);
108     virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
109                                 const char* szExtraInfoFormat, ...);
110     virtual void C_DECL  ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
111                                 const char* szExtraInfoFormat, ...);
112 #endif
113
114     virtual void setLimits(const TBuiltInResource&) = 0;
115
116     void checkIndex(const TSourceLoc&, const TType&, int& index);
117
118     EShLanguage getLanguage() const { return language; }
119     void setScanContext(TScanContext* c) { scanContext = c; }
120     TScanContext* getScanContext() const { return scanContext; }
121     void setPpContext(TPpContext* c) { ppContext = c; }
122     TPpContext* getPpContext() const { return ppContext; }
123
124     virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
125     virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
126     virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
127     virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
128     virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
129
130     virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
131     virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
132     virtual bool lineDirectiveShouldSetNextLine() const = 0;
133     virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
134
135     virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
136
137     virtual void notifyVersion(int line, int version, const char* type_string)
138     {
139         if (versionCallback)
140             versionCallback(line, version, type_string);
141     }
142     virtual void notifyErrorDirective(int line, const char* error_message)
143     {
144         if (errorCallback)
145             errorCallback(line, error_message);
146     }
147     virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
148     {
149         if (lineCallback)
150             lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
151     }
152     virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
153     {
154         if (extensionCallback)
155             extensionCallback(line, extension, behavior);
156     }
157
158     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
159     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
160
161     // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
162     virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
163
164     // Potentially rename shader entry point function
165     void renameShaderFunction(TString*& name) const
166     {
167         // Replace the entry point name given in the shader with the real entry point name,
168         // if there is a substitution.
169         if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0)
170             name = NewPoolTString(intermediate.getEntryPointName().c_str());
171     }
172
173     virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
174     virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
175
176     const char* const scopeMangler;
177
178     // Basic parsing state, easily accessible to the grammar
179
180     TSymbolTable& symbolTable;        // symbol table that goes with the current language, version, and profile
181     int statementNestingLevel;        // 0 if outside all flow control or compound statements
182     int loopNestingLevel;             // 0 if outside all loops
183     int structNestingLevel;           // 0 if outside structures
184     int blockNestingLevel;            // 0 if outside blocks
185     int controlFlowNestingLevel;      // 0 if outside all flow control
186     const TType* currentFunctionType; // the return type of the function that's currently being parsed
187     bool functionReturnsValue;        // true if a non-void function has a return
188     // if inside a function, true if the function is the entry point and this is after a return statement
189     bool postEntryPointReturn;
190     // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
191     TList<TIntermSequence*> switchSequenceStack;
192     // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
193     TList<int> switchLevel;
194     struct TPragma contextPragma;
195     int beginInvocationInterlockCount;
196     int endInvocationInterlockCount;
197
198 protected:
199     TParseContextBase(TParseContextBase&);
200     TParseContextBase& operator=(TParseContextBase&);
201
202     const bool parsingBuiltins;       // true if parsing built-in symbols/functions
203     TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
204     TScanContext* scanContext;
205     TPpContext* ppContext;
206     TBuiltInResource resources;
207     TLimits& limits;
208     TString sourceEntryPointName;
209
210     // These, if set, will be called when a line, pragma ... is preprocessed.
211     // They will be called with any parameters to the original directive.
212     std::function<void(int, int, bool, int, const char*)> lineCallback;
213     std::function<void(int, const TVector<TString>&)> pragmaCallback;
214     std::function<void(int, int, const char*)> versionCallback;
215     std::function<void(int, const char*, const char*)> extensionCallback;
216     std::function<void(int, const char*)> errorCallback;
217
218     // see implementation for detail
219     const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&,
220         std::function<bool(const TType&, const TType&, TOperator, int arg)>,
221         std::function<bool(const TType&, const TType&, const TType&)>,
222         /* output */ bool& tie);
223
224     virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size,
225                                       TSwizzleSelectors<TVectorSelector>&);
226
227     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
228     TVariable* globalUniformBlock;     // the actual block, inserted into the symbol table
229     unsigned int globalUniformBinding; // the block's binding number
230     unsigned int globalUniformSet;     // the block's set number
231     int firstNewMember;                // the index of the first member not yet inserted into the symbol table
232     // override this to set the language-specific name
233     virtual const char* getGlobalUniformBlockName() const { return ""; }
234     virtual void setUniformBlockDefaults(TType&) const { }
235     virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
236
237     // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
238     TMap<int, TVariable*> atomicCounterBuffers;
239     unsigned int atomicCounterBlockSet;
240     TMap<int, int> atomicCounterBlockFirstNewMember;
241     // override this to set the language-specific name
242     virtual const char* getAtomicCounterBlockName() const { return ""; }
243     virtual void setAtomicCounterBlockDefaults(TType&) const {}
244     virtual void setInvariant(const TSourceLoc&, const char*) {}
245     virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
246     bool isAtomicCounterBlock(const TSymbol& symbol) {
247         const TVariable* var = symbol.getAsVariable();
248         if (!var)
249             return false;
250         const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
251         return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
252     }
253
254     virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
255                                const char* szExtraInfoFormat, TPrefixType prefix,
256                                va_list args);
257     virtual void trackLinkage(TSymbol& symbol);
258     virtual void makeEditable(TSymbol*&);
259     virtual TVariable* getEditableVariable(const char* name);
260     virtual void finish();
261 };
262
263 //
264 // Manage the state for when to respect precision qualifiers and when to warn about
265 // the defaults being different than might be expected.
266 //
267 class TPrecisionManager {
268 public:
269     TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
270     virtual ~TPrecisionManager() {}
271
272     void respectPrecisionQualifiers() { obey = true; }
273     bool respectingPrecisionQualifiers() const { return obey; }
274     bool shouldWarnAboutDefaults() const { return warn; }
275     void defaultWarningGiven() { warn = false; }
276     void warnAboutDefaults() { warn = true; }
277     void explicitIntDefaultSeen()
278     {
279         explicitIntDefault = true;
280         if (explicitFloatDefault)
281             warn = false;
282     }
283     void explicitFloatDefaultSeen()
284     {
285         explicitFloatDefault = true;
286         if (explicitIntDefault)
287             warn = false;
288     }
289
290 protected:
291     bool obey;                  // respect precision qualifiers
292     bool warn;                  // need to give a warning about the defaults
293     bool explicitIntDefault;    // user set the default for int/uint
294     bool explicitFloatDefault;  // user set the default for float
295 };
296
297 //
298 // GLSL-specific parse helper.  Should have GLSL in the name, but that's
299 // too big of a change for comparing branches at the moment, and perhaps
300 // impacts downstream consumers as well.
301 //
302 class TParseContext : public TParseContextBase {
303 public:
304     TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
305                   bool forwardCompatible = false, EShMessages messages = EShMsgDefault,
306                   const TString* entryPoint = nullptr);
307     virtual ~TParseContext();
308
309     bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); }
310     void setPrecisionDefaults();
311
312     void setLimits(const TBuiltInResource&) override;
313     bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
314     void parserError(const char* s);     // for bison's yyerror
315
316     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
317     virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
318
319     void reservedErrorCheck(const TSourceLoc&, const TString&);
320     void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
321     bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
322     bool lineDirectiveShouldSetNextLine() const override;
323     bool builtInName(const TString&);
324
325     void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
326     TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
327     TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
328     void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
329
330 #ifndef GLSLANG_WEB
331     void makeEditable(TSymbol*&) override;
332     void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
333 #endif
334     bool isIoResizeArray(const TType&) const;
335     void fixIoArraySize(const TSourceLoc&, TType&);
336     void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
337     void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
338     int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const;
339     void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
340
341     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
342     TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
343     TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
344     TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
345     void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
346     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
347     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
348     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
349     TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function);
350     void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
351     TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
352     void checkLocation(const TSourceLoc&, TOperator);
353     TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
354     void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
355     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
356     TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
357     void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
358     void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
359     void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
360     void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
361     TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
362     void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
363     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
364     void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
365
366     TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
367     // returns true if the variable was remapped to something else
368     bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
369
370     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
371     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
372     void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
373     void variableCheck(TIntermTyped*& nodePtr);
374     bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
375     void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
376     void constantValueCheck(TIntermTyped* node, const char* token);
377     void integerCheck(const TIntermTyped* node, const char* token);
378     void globalCheck(const TSourceLoc&, const char* token);
379     bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
380     bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
381     void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType);
382     bool arrayQualifierError(const TSourceLoc&, const TQualifier&);
383     bool arrayError(const TSourceLoc&, const TType&);
384     void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
385     void structArrayCheck(const TSourceLoc&, const TType& structure);
386     void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember);
387     void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*);
388     bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
389     void boolCheck(const TSourceLoc&, const TIntermTyped*);
390     void boolCheck(const TSourceLoc&, const TPublicType&);
391     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
392     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
393     void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
394     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
395     void memberQualifierCheck(glslang::TPublicType&);
396     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
397     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
398     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
399     void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
400     void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier);
401     int computeSamplerTypeIndex(TSampler&);
402     TPrecisionQualifier getDefaultPrecision(TPublicType&);
403     void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&);
404     void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type);
405     bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
406     TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
407     void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
408     void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
409     void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
410     void nestedBlockCheck(const TSourceLoc&);
411     void nestedStructCheck(const TSourceLoc&);
412     void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
413     void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
414     void referenceCheck(const TSourceLoc&, const TType&, const char* op);
415     void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
416     void specializationCheck(const TSourceLoc&, const TType&, const char* op);
417     void structTypeCheck(const TSourceLoc&, TPublicType&);
418     void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
419     void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
420     void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
421
422     void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
423     void constantIndexExpressionCheck(TIntermNode*);
424
425     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
426     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
427     void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
428     void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
429     void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
430     void layoutTypeCheck(const TSourceLoc&, const TType&);
431     void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
432     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
433     void fixOffset(const TSourceLoc&, TSymbol&);
434
435     const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
436     const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
437     const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
438     const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
439     const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
440     void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
441     TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
442     TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
443     TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
444     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
445     void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
446     void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
447     void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
448     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
449     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
450     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
451     void fixXfbOffsets(TQualifier&, TTypeList&);
452     void fixBlockUniformOffsets(TQualifier&, TTypeList&);
453     void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
454     void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
455     void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
456     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
457     void invariantCheck(const TSourceLoc&, const TQualifier&);
458     void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
459     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
460     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
461     const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
462
463 #ifndef GLSLANG_WEB
464     TAttributeType attributeFromName(const TString& name) const;
465     TAttributes* makeAttributes(const TString& identifier) const;
466     TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
467     TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
468
469     // Determine selection control from attributes
470     void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
471     void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
472     // Determine loop control from attributes
473     void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
474     // Function attributes
475     void handleFunctionAttributes(const TSourceLoc&, const TAttributes&);
476
477     // GL_EXT_spirv_intrinsics
478     TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
479                                             const TIntermAggregate* extensions, const TIntermAggregate* capabilities);
480     TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
481                                                 TSpirvRequirement* spirvReq2);
482     TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
483     TSpirvTypeParameters* makeSpirvTypeParameters(const TPublicType& type);
484     TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
485                                                    TSpirvTypeParameters* spirvTypeParams2);
486     TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
487     TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value);
488     TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1,
489                                              TSpirvInstruction* spirvInst2);
490 #endif
491
492     void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
493
494 protected:
495     void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
496     void inheritGlobalDefaults(TQualifier& dst) const;
497     TVariable* makeInternalVariable(const char* name, const TType&) const;
498     TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
499     void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
500     void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&);
501     bool isRuntimeLength(const TIntermTyped&) const;
502     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
503     TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
504 #ifndef GLSLANG_WEB
505     void finish() override;
506 #endif
507
508     virtual const char* getGlobalUniformBlockName() const override;
509     virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
510     virtual void setUniformBlockDefaults(TType& block) const override;
511
512     virtual const char* getAtomicCounterBlockName() const override;
513     virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
514     virtual void setAtomicCounterBlockDefaults(TType& block) const override;
515     virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override;
516
517 public:
518     //
519     // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
520     //
521
522     // Current state of parsing
523     bool inMain;                 // if inside a function, true if the function is main
524     const TString* blockName;
525     TQualifier currentBlockQualifier;
526     TPrecisionQualifier defaultPrecision[EbtNumTypes];
527     TBuiltInResource resources;
528     TLimits& limits;
529
530 protected:
531     TParseContext(TParseContext&);
532     TParseContext& operator=(TParseContext&);
533
534     static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
535     TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
536     TPrecisionManager precisionManager;
537     TQualifier globalBufferDefaults;
538     TQualifier globalUniformDefaults;
539     TQualifier globalInputDefaults;
540     TQualifier globalOutputDefaults;
541     TQualifier globalSharedDefaults;
542     TString currentCaller;        // name of last function body entered (not valid when at global scope)
543 #ifndef GLSLANG_WEB
544     int* atomicUintOffsets;       // to become an array of the right size to hold an offset per binding point
545     bool anyIndexLimits;
546     TIdSetType inductiveLoopIds;
547     TVector<TIntermTyped*> needsIndexLimitationChecking;
548     TStructRecord matrixFixRecord;
549     TStructRecord packingFixRecord;
550
551     //
552     // Geometry shader input arrays:
553     //  - array sizing is based on input primitive and/or explicit size
554     //
555     // Tessellation control output arrays:
556     //  - array sizing is based on output layout(vertices=...) and/or explicit size
557     //
558     // Both:
559     //  - array sizing is retroactive
560     //  - built-in block redeclarations interact with this
561     //
562     // Design:
563     //  - use a per-context "resize-list", a list of symbols whose array sizes
564     //    can be fixed
565     //
566     //  - the resize-list starts empty at beginning of user-shader compilation, it does
567     //    not have built-ins in it
568     //
569     //  - on built-in array use: copyUp() symbol and add it to the resize-list
570     //
571     //  - on user array declaration: add it to the resize-list
572     //
573     //  - on block redeclaration: copyUp() symbol and add it to the resize-list
574     //     * note, that appropriately gives an error if redeclaring a block that
575     //       was already used and hence already copied-up
576     //
577     //  - on seeing a layout declaration that sizes the array, fix everything in the
578     //    resize-list, giving errors for mismatch
579     //
580     //  - on seeing an array size declaration, give errors on mismatch between it and previous
581     //    array-sizing declarations
582     //
583     TVector<TSymbol*> ioArraySymbolResizeList;
584 #endif
585 };
586
587 } // end namespace glslang
588
589 #endif // _PARSER_HELPER_INCLUDED_