Function for array indexing
| 1688 | |
| 1689 | // Function for array indexing |
| 1690 | void AddArrayIndexNode(const char* pos, unsigned argumentCount) |
| 1691 | { |
| 1692 | CodeInfo::lastKnownStartPos = pos; |
| 1693 | |
| 1694 | if(CodeInfo::nodeList[CodeInfo::nodeList.size() - argumentCount - 1]->typeInfo->refLevel == 2) |
| 1695 | { |
| 1696 | NodeZeroOP *array = CodeInfo::nodeList[CodeInfo::nodeList.size() - argumentCount - 1]; |
| 1697 | CodeInfo::nodeList.push_back(array); |
| 1698 | CodeInfo::nodeList.push_back(new NodeDereference()); |
| 1699 | array = CodeInfo::nodeList.back(); |
| 1700 | CodeInfo::nodeList.pop_back(); |
| 1701 | CodeInfo::nodeList[CodeInfo::nodeList.size() - argumentCount - 1] = array; |
| 1702 | } |
| 1703 | // Get array type |
| 1704 | TypeInfo *currentType = CodeInfo::nodeList[CodeInfo::nodeList.size()-2]->typeInfo; |
| 1705 | // Ignore errors only if we have one index and we are indexing array or a pointer to array |
| 1706 | if(AddFunctionCallNode(CodeInfo::lastKnownStartPos, "[]", argumentCount + 1, argumentCount == 1 && (currentType->arrLevel || (currentType->subType && currentType->subType->arrLevel)))) |
| 1707 | return; |
| 1708 | |
| 1709 | bool unifyTwo = false; |
| 1710 | // If it's an inplace array, set it to hidden variable, and put it's address on stack |
| 1711 | if(currentType->arrLevel != 0) |
| 1712 | { |
| 1713 | NodeZeroOP *index = CodeInfo::nodeList.back(); |
| 1714 | CodeInfo::nodeList.pop_back(); |
| 1715 | AddInplaceVariable(pos); |
| 1716 | currentType = CodeInfo::GetReferenceType(currentType); |
| 1717 | CodeInfo::nodeList.push_back(index); |
| 1718 | unifyTwo = true; |
| 1719 | } |
| 1720 | // Current type must be a reference to an array |
| 1721 | assert(currentType->refLevel && currentType->subType->arrLevel); |
| 1722 | |
| 1723 | // Get result type |
| 1724 | currentType = CodeInfo::GetDereferenceType(currentType); |
| 1725 | |
| 1726 | // If it is array without explicit size (pointer to array) |
| 1727 | if(currentType->arrSize == TypeInfo::UNSIZED_ARRAY) |
| 1728 | { |
| 1729 | // Then, before indexing it, we need to get address from this variable |
| 1730 | NodeZeroOP* temp = CodeInfo::nodeList.back(); |
| 1731 | CodeInfo::nodeList.pop_back(); |
| 1732 | CodeInfo::nodeList.push_back(new NodeDereference()); |
| 1733 | CodeInfo::nodeList.push_back(temp); |
| 1734 | } |
| 1735 | #ifndef NULLC_ENABLE_C_TRANSLATION |
| 1736 | // If index is a number and previous node is an address, then indexing can be done in compile-time |
| 1737 | if(CodeInfo::nodeList.back()->nodeType == typeNodeNumber && CodeInfo::nodeList[CodeInfo::nodeList.size()-2]->nodeType == typeNodeGetAddress) |
| 1738 | { |
| 1739 | // Get shift value |
| 1740 | int shiftValue = static_cast<NodeNumber*>(CodeInfo::nodeList.back())->GetInteger(); |
| 1741 | |
| 1742 | // Check bounds |
| 1743 | if(shiftValue < 0) |
| 1744 | ThrowError(pos, "ERROR: array index cannot be negative"); |
| 1745 | if((unsigned int)shiftValue >= currentType->arrSize) |
| 1746 | ThrowError(pos, "ERROR: array index out of bounds"); |
| 1747 |
no test coverage detected