Coverage Report

Created: 2025-08-03 07:23

/src/shaderc/third_party/glslang/glslang/MachineIndependent/ParseContextBase.cpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3
// Copyright (C) 2016 Google, Inc.
4
//
5
// All rights reserved.
6
//
7
// Redistribution and use in source and binary forms, with or without
8
// modification, are permitted provided that the following conditions
9
// are met:
10
//
11
//    Redistributions of source code must retain the above copyright
12
//    notice, this list of conditions and the following disclaimer.
13
//
14
//    Redistributions in binary form must reproduce the above
15
//    copyright notice, this list of conditions and the following
16
//    disclaimer in the documentation and/or other materials provided
17
//    with the distribution.
18
//
19
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20
//    contributors may be used to endorse or promote products derived
21
//    from this software without specific prior written permission.
22
//
23
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
// POSSIBILITY OF SUCH DAMAGE.
35
//
36
37
// Implement the TParseContextBase class.
38
39
#include <cstdarg>
40
41
#include "ParseHelper.h"
42
43
extern int yyparse(glslang::TParseContext*);
44
45
namespace glslang {
46
47
//
48
// Used to output syntax, parsing, and semantic errors.
49
//
50
51
void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason,
52
                                      const char* szToken,
53
                                      const char* szExtraInfoFormat,
54
                                      TPrefixType prefix, va_list args)
55
11.6M
{
56
11.6M
    const int maxSize = MaxTokenLength + 200;
57
11.6M
    char szExtraInfo[maxSize];
58
59
11.6M
    safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
60
61
11.6M
    infoSink.info.prefix(prefix);
62
11.6M
    infoSink.info.location(loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
63
11.6M
    infoSink.info << "'" << szToken <<  "' : " << szReason << " " << szExtraInfo << "\n";
64
65
11.6M
    if (prefix == EPrefixError) {
66
11.6M
        ++numErrors;
67
11.6M
    }
68
11.6M
}
69
70
void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
71
                                     const char* szExtraInfoFormat, ...)
72
11.1M
{
73
11.1M
    if (messages & EShMsgOnlyPreprocessor)
74
3.74M
        return;
75
    // If enhanced msg readability, only print one error
76
7.36M
    if (messages & EShMsgEnhanced && numErrors > 0)
77
0
        return;
78
7.36M
    va_list args;
79
7.36M
    va_start(args, szExtraInfoFormat);
80
7.36M
    outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
81
7.36M
    va_end(args);
82
83
7.36M
    if ((messages & EShMsgCascadingErrors) == 0)
84
3.91k
        currentScanner->setEndOfInput();
85
7.36M
}
86
87
void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
88
                                    const char* szExtraInfoFormat, ...)
89
7.07k
{
90
7.07k
    if (suppressWarnings())
91
0
        return;
92
7.07k
    va_list args;
93
7.07k
    va_start(args, szExtraInfoFormat);
94
7.07k
    outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
95
7.07k
    va_end(args);
96
7.07k
}
97
98
void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
99
                                       const char* szExtraInfoFormat, ...)
100
4.31M
{
101
4.31M
    va_list args;
102
4.31M
    va_start(args, szExtraInfoFormat);
103
4.31M
    outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
104
4.31M
    va_end(args);
105
106
4.31M
    if ((messages & EShMsgCascadingErrors) == 0)
107
0
        currentScanner->setEndOfInput();
108
4.31M
}
109
110
void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
111
                                      const char* szExtraInfoFormat, ...)
112
2.50k
{
113
2.50k
    va_list args;
114
2.50k
    va_start(args, szExtraInfoFormat);
115
2.50k
    outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
116
2.50k
    va_end(args);
117
2.50k
}
118
119
//
120
// Both test and if necessary, spit out an error, to see if the node is really
121
// an l-value that can be operated on this way.
122
//
123
// Returns true if there was an error.
124
//
125
bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
126
680k
{
127
680k
    TIntermBinary* binaryNode = node->getAsBinaryNode();
128
129
680k
    const char* symbol = nullptr;
130
680k
    TIntermSymbol* symNode = node->getAsSymbolNode();
131
680k
    if (symNode != nullptr)
132
584k
        symbol = symNode->getName().c_str();
133
134
680k
    const char* message = nullptr;
135
680k
    switch (node->getQualifier().storage) {
136
1.25k
    case EvqConst:          message = "can't modify a const";        break;
137
16
    case EvqConstReadOnly:  message = "can't modify a const";        break;
138
3.37k
    case EvqUniform:        message = "can't modify a uniform";      break;
139
88.5k
    case EvqBuffer:
140
88.5k
        if (node->getQualifier().isReadOnly())
141
0
            message = "can't modify a readonly buffer";
142
88.5k
        if (node->getQualifier().isShaderRecord())
143
0
            message = "can't modify a shaderrecordnv qualified buffer";
144
88.5k
        break;
145
0
    case EvqHitAttr:
146
0
        if (language != EShLangIntersect)
147
0
            message = "cannot modify hitAttributeNV in this stage";
148
0
        break;
149
150
587k
    default:
151
        //
152
        // Type that can't be written to?
153
        //
154
587k
        switch (node->getBasicType()) {
155
0
        case EbtSampler:
156
0
            if (extensionTurnedOn(E_GL_ARB_bindless_texture) == false)
157
0
                message = "can't modify a sampler";
158
0
            break;
159
6
        case EbtVoid:
160
6
            message = "can't modify void";
161
6
            break;
162
0
        case EbtAtomicUint:
163
0
            message = "can't modify an atomic_uint";
164
0
            break;
165
0
        case EbtAccStruct:
166
0
            message = "can't modify accelerationStructureNV";
167
0
            break;
168
3
        case EbtRayQuery:
169
3
            message = "can't modify rayQueryEXT";
170
3
            break;
171
0
        case EbtHitObjectNV:
172
0
            message = "can't modify hitObjectNV";
173
0
            break;
174
587k
        default:
175
587k
            break;
176
587k
        }
177
680k
    }
178
179
680k
    if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
180
1.02k
        error(loc, " l-value required", op, "", "");
181
182
1.02k
        return true;
183
1.02k
    }
184
185
    //
186
    // Everything else is okay, no error.
187
    //
188
679k
    if (message == nullptr)
189
674k
    {
190
674k
        if (binaryNode) {
191
93.7k
            switch (binaryNode->getOp()) {
192
45.7k
            case EOpIndexDirect:
193
46.7k
            case EOpIndexIndirect:     // fall through
194
93.6k
            case EOpIndexDirectStruct: // fall through
195
93.7k
            case EOpVectorSwizzle:
196
93.7k
            case EOpMatrixSwizzle:
197
93.7k
                return lValueErrorCheck(loc, op, binaryNode->getLeft());
198
47
            default:
199
47
                break;
200
93.7k
            }
201
47
            error(loc, " l-value required", op, "", "");
202
203
47
            return true;
204
93.7k
        }
205
581k
        return false;
206
674k
    }
207
208
    //
209
    // If we get here, we have an error and a message.
210
    //
211
4.65k
    const TIntermTyped* leftMostTypeNode = TIntermediate::traverseLValueBase(node, true);
212
213
4.65k
    if (symNode)
214
3.28k
        error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
215
1.36k
    else
216
1.36k
        if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct)
217
108
            if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
218
107
                error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message);
219
1
            else
220
1
                error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message);
221
1.25k
        else
222
1.25k
            error(loc, " l-value required", op, "(%s)", message);
223
224
4.65k
    return true;
225
679k
}
226
227
// Test for and give an error if the node can't be read from.
228
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
229
7.70M
{
230
7.70M
    if (! node)
231
0
        return;
232
233
7.70M
    TIntermBinary* binaryNode = node->getAsBinaryNode();
234
7.70M
    const TIntermSymbol* symNode = node->getAsSymbolNode();
235
236
7.70M
    if (node->getQualifier().isWriteOnly()) {
237
9
        const TIntermTyped* leftMostTypeNode = TIntermediate::traverseLValueBase(node, true);
238
239
9
        if (symNode != nullptr)
240
9
            error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
241
0
        else if (binaryNode &&
242
0
                (binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
243
0
                 binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
244
0
            if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
245
0
                error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
246
0
            else
247
0
                error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str());
248
0
        else
249
0
            error(loc, "can't read from writeonly object: ", op, "");
250
251
7.70M
    } else {
252
7.70M
        if (binaryNode) {
253
328k
            switch (binaryNode->getOp()) {
254
34.9k
            case EOpIndexDirect:
255
42.9k
            case EOpIndexIndirect:
256
66.1k
            case EOpIndexDirectStruct:
257
73.0k
            case EOpVectorSwizzle:
258
73.0k
            case EOpMatrixSwizzle:
259
73.0k
                rValueErrorCheck(loc, op, binaryNode->getLeft());
260
73.0k
                break;
261
255k
            default:
262
255k
                break;
263
328k
            }
264
328k
        }
265
7.70M
    }
266
7.70M
}
267
268
// Add 'symbol' to the list of deferred linkage symbols, which
269
// are later processed in finish(), at which point the symbol
270
// must still be valid.
271
// It is okay if the symbol's type will be subsequently edited;
272
// the modifications will be tracked.
273
// Order is preserved, to avoid creating novel forward references.
274
void TParseContextBase::trackLinkage(TSymbol& symbol)
275
11.5M
{
276
11.5M
    if (!parsingBuiltins)
277
303k
        linkageSymbols.push_back(&symbol);
278
11.5M
}
279
280
// Ensure index is in bounds, correct if necessary.
281
// Give an error if not.
282
void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
283
68.2k
{
284
68.2k
    const auto sizeIsSpecializationExpression = [&type]() {
285
54.2k
        return type.containsSpecializationSize() &&
286
54.2k
               type.getArraySizes()->getOuterNode() != nullptr &&
287
54.2k
               type.getArraySizes()->getOuterNode()->getAsSymbolNode() == nullptr; };
288
289
68.2k
    if (index < 0) {
290
323
        error(loc, "", "[", "index out of range '%d'", index);
291
323
        index = 0;
292
67.9k
    } else if (type.isArray()) {
293
55.8k
        if (type.isSizedArray() && !sizeIsSpecializationExpression() &&
294
55.8k
            index >= type.getOuterArraySize()) {
295
767
            error(loc, "", "[", "array index out of range '%d'", index);
296
767
            index = type.getOuterArraySize() - 1;
297
767
        }
298
55.8k
    } else if (type.isVector()) {
299
6.47k
        if (index >= type.getVectorSize()) {
300
197
            error(loc, "", "[", "vector index out of range '%d'", index);
301
197
            index = type.getVectorSize() - 1;
302
197
        }
303
6.47k
    } else if (type.isMatrix()) {
304
5.64k
        if (index >= type.getMatrixCols()) {
305
89
            error(loc, "", "[", "matrix index out of range '%d'", index);
306
89
            index = type.getMatrixCols() - 1;
307
89
        }
308
5.64k
    } else if (type.isCoopVecNV()) {
309
0
        if (index >= type.computeNumComponents()) {
310
0
            error(loc, "", "[", "cooperative vector index out of range '%d'", index);
311
0
            index = type.computeNumComponents() - 1;
312
0
        }
313
0
    }
314
68.2k
}
315
316
// Make a shared symbol have a non-shared version that can be edited by the current
317
// compile, such that editing its type will not change the shared version and will
318
// effect all nodes already sharing it (non-shallow type),
319
// or adopting its full type after being edited (shallow type).
320
void TParseContextBase::makeEditable(TSymbol*& symbol)
321
858
{
322
    // copyUp() does a deep copy of the type.
323
858
    symbol = symbolTable.copyUp(symbol);
324
325
    // Save it (deferred, so it can be edited first) in the AST for linker use.
326
858
    if (symbol)
327
858
        trackLinkage(*symbol);
328
858
}
329
330
// Return a writable version of the variable 'name'.
331
//
332
// Return nullptr if 'name' is not found.  This should mean
333
// something is seriously wrong (e.g., compiler asking self for
334
// built-in that doesn't exist).
335
TVariable* TParseContextBase::getEditableVariable(const char* name)
336
0
{
337
0
    bool builtIn;
338
0
    TSymbol* symbol = symbolTable.find(name, &builtIn);
339
340
0
    assert(symbol != nullptr);
341
0
    if (symbol == nullptr)
342
0
        return nullptr;
343
344
0
    if (builtIn)
345
0
        makeEditable(symbol);
346
347
0
    return symbol->getAsVariable();
348
0
}
349
350
// Select the best matching function for 'call' from 'candidateList'.
351
//
352
// Assumptions
353
//
354
// There is no exact match, so a selection algorithm needs to run. That is, the
355
// language-specific handler should check for exact match first, to
356
// decide what to do, before calling this selector.
357
//
358
// Input
359
//
360
//  * list of candidate signatures to select from
361
//  * the call
362
//  * a predicate function convertible(from, to) that says whether or not type
363
//    'from' can implicitly convert to type 'to' (it includes the case of what
364
//    the calling language would consider a matching type with no conversion
365
//    needed)
366
//  * a predicate function better(from1, from2, to1, to2) that says whether or
367
//    not a conversion from <-> to2 is considered better than a conversion
368
//    from <-> to1 (both in and out directions need testing, as declared by the
369
//    formal parameter)
370
//
371
// Output
372
//
373
//  * best matching candidate (or none, if no viable candidates found)
374
//  * whether there was a tie for the best match (ambiguous overload selection,
375
//    caller's choice for how to report)
376
//
377
const TFunction* TParseContextBase::selectFunction(
378
    const TVector<const TFunction*> candidateList,
379
    const TFunction& call,
380
    std::function<bool(const TType& from, const TType& to, TOperator op, int arg)> convertible,
381
    std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
382
    /* output */ bool& tie)
383
91.9k
{
384
//
385
// Operation
386
//
387
// 1. Prune the input list of candidates down to a list of viable candidates,
388
// where each viable candidate has
389
//
390
//  * at least as many parameters as there are calling arguments, with any
391
//    remaining parameters being optional or having default values
392
//  * each parameter is true under convertible(A, B), where A is the calling
393
//    type for in and B is the formal type, and in addition, for out B is the
394
//    calling type and A is the formal type
395
//
396
// 2. If there are no viable candidates, return with no match.
397
//
398
// 3. If there is only one viable candidate, it is the best match.
399
//
400
// 4. If there are multiple viable candidates, select the first viable candidate
401
// as the incumbent. Compare the incumbent to the next viable candidate, and if
402
// that candidate is better (bullets below), make it the incumbent. Repeat, with
403
// a linear walk through the viable candidate list. The final incumbent will be
404
// returned as the best match. A viable candidate is better than the incumbent if
405
//
406
//  * it has a function argument with a better(...) conversion than the incumbent,
407
//    for all directions needed by in and out
408
//  * the incumbent has no argument with a better(...) conversion then the
409
//    candidate, for either in or out (as needed)
410
//
411
// 5. Check for ambiguity by comparing the best match against all other viable
412
// candidates. If any other viable candidate has a function argument with a
413
// better(...) conversion than the best candidate (for either in or out
414
// directions), return that there was a tie for best.
415
//
416
417
91.9k
    tie = false;
418
419
    // 1. prune to viable...
420
91.9k
    TVector<const TFunction*> viableCandidates;
421
2.18M
    for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
422
2.09M
        const TFunction& candidate = *(*it);
423
424
        // to even be a potential match, number of arguments must be >= the number of
425
        // fixed (non-default) parameters, and <= the total (including parameter with defaults).
426
2.09M
        if (call.getParamCount() < candidate.getFixedParamCount() ||
427
2.09M
            call.getParamCount() > candidate.getParamCount())
428
890k
            continue;
429
430
        // see if arguments are convertible
431
1.20M
        bool viable = true;
432
433
        // The call can have fewer parameters than the candidate, if some have defaults.
434
1.20M
        const int paramCount = std::min(call.getParamCount(), candidate.getParamCount());
435
1.53M
        for (int param = 0; param < paramCount; ++param) {
436
1.35M
            if (candidate[param].type->getQualifier().isParamInput()) {
437
1.34M
                if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) {
438
1.02M
                    viable = false;
439
1.02M
                    break;
440
1.02M
                }
441
1.34M
            }
442
326k
            if (candidate[param].type->getQualifier().isParamOutput()) {
443
4.33k
                if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) {
444
704
                    viable = false;
445
704
                    break;
446
704
                }
447
4.33k
            }
448
326k
        }
449
450
1.20M
        if (viable)
451
178k
            viableCandidates.push_back(&candidate);
452
1.20M
    }
453
454
    // 2. none viable...
455
91.9k
    if (viableCandidates.size() == 0)
456
70.8k
        return nullptr;
457
458
    // 3. only one viable...
459
21.0k
    if (viableCandidates.size() == 1)
460
5.14k
        return viableCandidates.front();
461
462
    // 4. find best...
463
330k
    const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
464
        // is call -> can2 better than call -> can1 for any parameter
465
330k
        bool hasBetterParam = false;
466
796k
        for (int param = 0; param < call.getParamCount(); ++param) {
467
484k
            if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
468
17.8k
                hasBetterParam = true;
469
17.8k
                break;
470
17.8k
            }
471
484k
        }
472
330k
        return hasBetterParam;
473
330k
    };
474
475
156k
    const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
476
        // is call -> can2 equivalent to call -> can1 for all the call parameters?
477
186k
        for (int param = 0; param < call.getParamCount(); ++param) {
478
164k
            if (better(*call[param].type, *can1[param].type, *can2[param].type) ||
479
164k
                better(*call[param].type, *can2[param].type, *can1[param].type))
480
134k
                return false;
481
164k
        }
482
21.9k
        return true;
483
156k
    };
484
485
15.9k
    const TFunction* incumbent = viableCandidates.front();
486
173k
    for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
487
157k
        const TFunction& candidate = *(*it);
488
157k
        if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
489
13.3k
            incumbent = &candidate;
490
157k
    }
491
492
    // 5. ambiguity...
493
189k
    for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
494
173k
        if (incumbent == *it)
495
15.9k
            continue;
496
157k
        const TFunction& candidate = *(*it);
497
498
        // In the case of default parameters, it may have an identical initial set, which is
499
        // also ambiguous
500
157k
        if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate))
501
23.2k
            tie = true;
502
157k
    }
503
504
15.9k
    return incumbent;
505
21.0k
}
506
507
//
508
// Look at a '.' field selector string and change it into numerical selectors
509
// for a vector or scalar.
510
//
511
// Always return some form of swizzle, so the result is always usable.
512
//
513
void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize,
514
                                             TSwizzleSelectors<TVectorSelector>& selector)
515
115k
{
516
    // Too long?
517
115k
    if (compString.size() > MaxSwizzleSelectors)
518
1.34k
        error(loc, "vector swizzle too long", compString.c_str(), "");
519
520
    // Use this to test that all swizzle characters are from the same swizzle-namespace-set
521
115k
    enum {
522
115k
        exyzw,
523
115k
        ergba,
524
115k
        estpq,
525
115k
    } fieldSet[MaxSwizzleSelectors];
526
527
    // Decode the swizzle string.
528
115k
    int size = std::min(MaxSwizzleSelectors, (int)compString.size());
529
281k
    for (int i = 0; i < size; ++i) {
530
166k
        switch (compString[i])  {
531
82.5k
        case 'x':
532
82.5k
            selector.push_back(0);
533
82.5k
            fieldSet[i] = exyzw;
534
82.5k
            break;
535
5.07k
        case 'r':
536
5.07k
            selector.push_back(0);
537
5.07k
            fieldSet[i] = ergba;
538
5.07k
            break;
539
1.88k
        case 's':
540
1.88k
            selector.push_back(0);
541
1.88k
            fieldSet[i] = estpq;
542
1.88k
            break;
543
544
38.6k
        case 'y':
545
38.6k
            selector.push_back(1);
546
38.6k
            fieldSet[i] = exyzw;
547
38.6k
            break;
548
3.84k
        case 'g':
549
3.84k
            selector.push_back(1);
550
3.84k
            fieldSet[i] = ergba;
551
3.84k
            break;
552
1.47k
        case 't':
553
1.47k
            selector.push_back(1);
554
1.47k
            fieldSet[i] = estpq;
555
1.47k
            break;
556
557
17.6k
        case 'z':
558
17.6k
            selector.push_back(2);
559
17.6k
            fieldSet[i] = exyzw;
560
17.6k
            break;
561
3.88k
        case 'b':
562
3.88k
            selector.push_back(2);
563
3.88k
            fieldSet[i] = ergba;
564
3.88k
            break;
565
395
        case 'p':
566
395
            selector.push_back(2);
567
395
            fieldSet[i] = estpq;
568
395
            break;
569
570
3.94k
        case 'w':
571
3.94k
            selector.push_back(3);
572
3.94k
            fieldSet[i] = exyzw;
573
3.94k
            break;
574
2.61k
        case 'a':
575
2.61k
            selector.push_back(3);
576
2.61k
            fieldSet[i] = ergba;
577
2.61k
            break;
578
57
        case 'q':
579
57
            selector.push_back(3);
580
57
            fieldSet[i] = estpq;
581
57
            break;
582
583
3.97k
        default:
584
3.97k
            error(loc, "unknown swizzle selection", compString.c_str(), "");
585
3.97k
            break;
586
166k
        }
587
166k
    }
588
589
    // Additional error checking.
590
271k
    for (int i = 0; i < selector.size(); ++i) {
591
160k
        if (selector[i] >= vecSize) {
592
4.06k
            error(loc, "vector swizzle selection out of range",  compString.c_str(), "");
593
4.06k
            selector.resize(i);
594
4.06k
            break;
595
4.06k
        }
596
597
156k
        if (i > 0 && fieldSet[i] != fieldSet[i-1]) {
598
735
            error(loc, "vector swizzle selectors not from the same set", compString.c_str(), "");
599
735
            selector.resize(i);
600
735
            break;
601
735
        }
602
156k
    }
603
604
    // Ensure it is valid.
605
115k
    if (selector.size() == 0)
606
3.10k
        selector.push_back(0);
607
115k
}
608
609
//
610
// Make the passed-in variable information become a member of the
611
// global uniform block.  If this doesn't exist yet, make it.
612
//
613
void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
614
4.52k
{
615
    // Make the global block, if not yet made.
616
4.52k
    if (globalUniformBlock == nullptr) {
617
1.11k
        TQualifier blockQualifier;
618
1.11k
        blockQualifier.clear();
619
1.11k
        blockQualifier.storage = EvqUniform;
620
1.11k
        TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
621
1.11k
        setUniformBlockDefaults(blockType);
622
1.11k
        globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
623
1.11k
        firstNewMember = 0;
624
1.11k
    }
625
626
    // Update with binding and set
627
4.52k
    globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
628
4.52k
    globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
629
630
    // Check for declarations of this default uniform that already exist due to other compilation units.
631
4.52k
    TSymbol* symbol = symbolTable.find(memberName);
632
4.52k
    if (symbol) {
633
238
        if (memberType != symbol->getType()) {
634
46
            TString err;
635
46
            err += "Redeclaration: already declared as \"" + symbol->getType().getCompleteString() + "\"";
636
46
            error(loc, "", memberName.c_str(), err.c_str());
637
46
        }
638
238
        return;
639
238
    }
640
641
    // Add the requested member as a member to the global block.
642
4.28k
    TType* type = new TType;
643
4.28k
    type->shallowCopy(memberType);
644
4.28k
    type->setFieldName(memberName);
645
4.28k
    if (typeList)
646
6
        type->setStruct(typeList);
647
4.28k
    TTypeLoc typeLoc = {type, loc};
648
4.28k
    globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
649
650
    // Insert into the symbol table.
651
4.28k
    if (firstNewMember == 0) {
652
        // This is the first request; we need a normal symbol table insert
653
1.10k
        if (symbolTable.insert(*globalUniformBlock))
654
1.10k
            trackLinkage(*globalUniformBlock);
655
0
        else
656
0
            error(loc, "failed to insert the global constant buffer", "uniform", "");
657
3.18k
    } else {
658
        // This is a follow-on request; we need to amend the first insert
659
3.18k
        symbolTable.amend(*globalUniformBlock, firstNewMember);
660
3.18k
    }
661
662
4.28k
    ++firstNewMember;
663
4.28k
}
664
665
0
void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) {
666
    // Make the atomic counter block, if not yet made.
667
0
    const auto &at  = atomicCounterBuffers.find(binding);
668
0
    if (at == atomicCounterBuffers.end()) {
669
0
        atomicCounterBuffers.insert({binding, (TVariable*)nullptr });
670
0
        atomicCounterBlockFirstNewMember.insert({binding, 0});
671
0
    }
672
673
0
    TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding];
674
0
    int& bufferNewMember = atomicCounterBlockFirstNewMember[binding];
675
676
0
    if (atomicCounterBuffer == nullptr) {
677
0
        TQualifier blockQualifier;
678
0
        blockQualifier.clear();
679
0
        blockQualifier.storage = EvqBuffer;
680
        
681
0
        char charBuffer[512];
682
0
        if (binding != TQualifier::layoutBindingEnd) {
683
0
            snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding);
684
0
        } else {
685
0
            snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName());
686
0
        }
687
        
688
0
        TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier);
689
0
        setUniformBlockDefaults(blockType);
690
0
        blockType.getQualifier().layoutPacking = ElpStd430;
691
0
        atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true);
692
        // If we arn't auto mapping bindings then set the block to use the same
693
        // binding as what the atomic was set to use
694
0
        if (!intermediate.getAutoMapBindings()) {
695
0
            atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding;
696
0
        }
697
0
        bufferNewMember = 0;
698
699
0
        atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet;
700
0
    }
701
702
    // Add the requested member as a member to the global block.
703
0
    TType* type = new TType;
704
0
    type->shallowCopy(memberType);
705
0
    type->setFieldName(memberName);
706
0
    if (typeList)
707
0
        type->setStruct(typeList);
708
0
    TTypeLoc typeLoc = {type, loc};
709
0
    atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc);
710
711
    // Insert into the symbol table.
712
0
    if (bufferNewMember == 0) {
713
        // This is the first request; we need a normal symbol table insert
714
0
        if (symbolTable.insert(*atomicCounterBuffer))
715
0
            trackLinkage(*atomicCounterBuffer);
716
0
        else
717
0
            error(loc, "failed to insert the global constant buffer", "buffer", "");
718
0
    } else {
719
        // This is a follow-on request; we need to amend the first insert
720
0
        symbolTable.amend(*atomicCounterBuffer, bufferNewMember);
721
0
    }
722
723
0
    ++bufferNewMember;
724
0
}
725
726
void TParseContextBase::finish()
727
333k
{
728
333k
    if (parsingBuiltins)
729
294k
        return;
730
731
38.4k
    for (const TString& relaxedSymbol : relaxedSymbols)
732
0
    {
733
0
        TSymbol* symbol = symbolTable.find(relaxedSymbol);
734
0
        TType& type = symbol->getWritableType();
735
0
        for (const TTypeLoc& typeLoc : *type.getStruct())
736
0
        {
737
0
            if (typeLoc.type->isOpaque())
738
0
            {
739
0
                typeLoc.type->getSampler() = TSampler{};
740
0
                typeLoc.type->setBasicType(EbtInt);
741
0
                TString fieldName("/*");
742
0
                fieldName.append(typeLoc.type->getFieldName());
743
0
                fieldName.append("*/");
744
0
                typeLoc.type->setFieldName(fieldName);
745
0
            }
746
0
        }
747
0
    }
748
749
    // Transfer the linkage symbols to AST nodes, preserving order.
750
38.4k
    TIntermAggregate* linkage = new TIntermAggregate;
751
332k
    for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
752
294k
        intermediate.addSymbolLinkageNode(linkage, **i);
753
38.4k
    intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable);
754
38.4k
}
755
756
} // end namespace glslang