// For initializer lists, we have to const-fold into a constructor for the type, so build
// that.
- TFunction* constructor = parseContext.handleConstructorCall(token.loc, type);
+ TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
if (constructor == nullptr) // cannot construct
return false;
return false;
// Hook it up like a constructor
- TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType);
+ TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
if (constructorFunction == nullptr) {
expected("type that can be constructed");
return false;
// type
TType type;
if (acceptType(type)) {
- TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
+ TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
if (constructorFunction == nullptr)
return false;
//
// It's a constructor, of type 'type'.
//
- result = addConstructor(loc, arguments, type);
+ result = handleConstructor(loc, arguments, type);
if (result == nullptr)
error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
}
}
//
-// Handle seeing a built-in constructor in a grammar production.
+// Handle seeing something in a grammar production that can be done by calling
+// a constructor.
//
-TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const TType& type)
+// The constructor still must be "handled" by handleFunctionCall(), which will
+// then call handleConstructor().
+//
+TFunction* HlslParseContext::makeConstructorCall(const TSourceLoc& loc, const TType& type)
{
TOperator op = intermediate.mapTypeToConstructorOp(type);
// Now that the subtree is processed, process this node as if the
// initializer list is a set of arguments to a constructor.
- TIntermNode* emulatedConstructorArguments;
+ TIntermTyped* emulatedConstructorArguments;
if (initList->getSequence().size() == 1)
- emulatedConstructorArguments = initList->getSequence()[0];
+ emulatedConstructorArguments = initList->getSequence()[0]->getAsTyped();
else
emulatedConstructorArguments = initList;
//
// Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
//
-TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type)
+TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type)
{
- if (node == nullptr || node->getAsTyped() == nullptr)
+ if (node == nullptr)
return nullptr;
// Handle the idiom "(struct type)0"
+ // Sequences (in an aggregate) for initialization are not yet tagged with
+ // an operator or type, so it is too early to ask if they are scalars.
if (type.isStruct() && isZeroConstructor(node))
return convertInitializerList(loc, type, intermediate.makeAggregate(loc));
+ return addConstructor(loc, node, type);
+}
+
+// Add a constructor, either from the grammar, or other programmatic reasons.
+//
+// Return nullptr if it can't be done.
+//
+TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type)
+{
TIntermAggregate* aggrNode = node->getAsAggregate();
TOperator op = intermediate.mapTypeToConstructorOp(type);
else if (op == EOpConstructStruct)
newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc());
else
- newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
+ newNode = constructBuiltIn(type, op, node, node->getLoc(), false);
if (newNode && (type.isArray() || op == EOpConstructStruct))
newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
void addInputArgumentConversions(const TFunction&, TIntermTyped*&);
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
- TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
+ TFunction* makeConstructorCall(const TSourceLoc&, const TType&);
void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase);
void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location,
const glslang::TString* component);
TSymbol* lookupUserType(const TString&, TType&);
TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = 0);
void lengthenList(const TSourceLoc&, TIntermSequence& list, int size);
- TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
+ TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
+ TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0);