// // Make sure there is enough data provided to the constructor to build // something of the type of the constructor. Also returns the type of // the constructor. // // Returns true if there was an error in construction. // bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type) { *type = function.getReturnType(); bool constructingMatrix = false; switch(op) { case EOpConstructMat2: case EOpConstructMat3: case EOpConstructMat4: constructingMatrix = true; break; default: break; } // // Note: It's okay to have too many components available, but not okay to have unused // arguments. 'full' will go to true when enough args have been seen. If we loop // again, there is an extra argument, so 'overfull' will become true. // int size = 0; bool constType = true; bool full = false; bool overFull = false; bool matrixInMatrix = false; bool arrayArg = false; for (int i = 0; i < function.getParamCount(); ++i) { const TParameter& param = function.getParam(i); size += param.type->getObjectSize(); if (constructingMatrix && param.type->isMatrix()) matrixInMatrix = true; if (full) overFull = true; if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) full = true; if (param.type->getQualifier() != EvqConst) constType = false; if (param.type->isArray()) arrayArg = true; } if (constType) type->setQualifier(EvqConst); if (type->isArray() && type->getArraySize() != function.getParamCount()) { error(line, "array constructor needs one argument per array element", "constructor", ""); return true; } if (arrayArg && op != EOpConstructStruct) { error(line, "constructing from a non-dereferenced array", "constructor", ""); return true; } if (matrixInMatrix && !type->isArray()) { if (function.getParamCount() != 1) { error(line, "constructing matrix from matrix can only take one argument", "constructor", ""); return true; } } if (overFull) { error(line, "too many arguments", "constructor", ""); return true; } if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) { error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); return true; } if (!type->isMatrix() || !matrixInMatrix) { if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || (op == EOpConstructStruct && size < type->getObjectSize())) { error(line, "not enough data provided for construction", "constructor", ""); return true; } } TIntermTyped *typed = node ? node->getAsTyped() : 0; if (typed == 0) { error(line, "constructor argument does not have a type", "constructor", ""); return true; } if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { error(line, "cannot convert a sampler", "constructor", ""); return true; } if (typed->getBasicType() == EbtVoid) { error(line, "cannot convert a void", "constructor", ""); return true; } return false; }