Handle seeing a variable identifier in the grammar.
| 449 | // Handle seeing a variable identifier in the grammar. |
| 450 | // |
| 451 | TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string) |
| 452 | { |
| 453 | TIntermTyped* node = nullptr; |
| 454 | |
| 455 | // Error check for requiring specific extensions present. |
| 456 | if (symbol && symbol->getNumExtensions()) |
| 457 | requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); |
| 458 | |
| 459 | if (symbol && symbol->isReadOnly()) { |
| 460 | // All shared things containing an unsized array must be copied up |
| 461 | // on first use, so that all future references will share its array structure, |
| 462 | // so that editing the implicit size will effect all nodes consuming it, |
| 463 | // and so that editing the implicit size won't change the shared one. |
| 464 | // |
| 465 | // If this is a variable or a block, check it and all it contains, but if this |
| 466 | // is a member of an anonymous block, check the whole block, as the whole block |
| 467 | // will need to be copied up if it contains an unsized array. |
| 468 | // |
| 469 | // This check is being done before the block-name check further down, so guard |
| 470 | // for that too. |
| 471 | if (!symbol->getType().isUnusableName()) { |
| 472 | if (symbol->getType().containsUnsizedArray() || |
| 473 | (symbol->getAsAnonMember() && |
| 474 | symbol->getAsAnonMember()->getAnonContainer().getType().containsUnsizedArray())) |
| 475 | makeEditable(symbol); |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | const TVariable* variable; |
| 480 | const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; |
| 481 | if (anon) { |
| 482 | // It was a member of an anonymous container. |
| 483 | |
| 484 | // Create a subtree for its dereference. |
| 485 | variable = anon->getAnonContainer().getAsVariable(); |
| 486 | TIntermTyped* container = intermediate.addSymbol(*variable, loc); |
| 487 | TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); |
| 488 | node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); |
| 489 | |
| 490 | node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); |
| 491 | if (node->getType().hiddenMember()) |
| 492 | error(loc, "member of nameless block was not redeclared", string->c_str(), ""); |
| 493 | } else { |
| 494 | // Not a member of an anonymous container. |
| 495 | |
| 496 | // The symbol table search was done in the lexical phase. |
| 497 | // See if it was a variable. |
| 498 | variable = symbol ? symbol->getAsVariable() : nullptr; |
| 499 | if (variable) { |
| 500 | if (variable->getType().isUnusableName()) { |
| 501 | error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); |
| 502 | variable = nullptr; |
| 503 | } |
| 504 | |
| 505 | if (language == EShLangMesh && variable) { |
| 506 | TLayoutGeometry primitiveType = intermediate.getOutputPrimitive(); |
| 507 | if ((variable->getMangledName() == "gl_PrimitiveTriangleIndicesEXT" && primitiveType != ElgTriangles) || |
| 508 | (variable->getMangledName() == "gl_PrimitiveLineIndicesEXT" && primitiveType != ElgLines) || |
no test coverage detected