// typedef
bool typedefDecl = acceptTokenClass(EHTokTypedef);
- TType type;
+ TType declaredType;
// DX9 sampler declaration use a different syntax
// DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
// As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
// For that reason, this line is commented out
- // if (acceptSamplerDeclarationDX9(type))
+ // if (acceptSamplerDeclarationDX9(declaredType))
// return true;
// fully_specified_type
- if (! acceptFullySpecifiedType(type))
+ if (! acceptFullySpecifiedType(declaredType))
return false;
- if (type.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) {
- if (type.getBasicType() == EbtSampler) {
+ if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) {
+ if (declaredType.getBasicType() == EbtSampler) {
// Sampler/textures are uniform by default (if no explicit qualifier is present) in
// HLSL. This line silently converts samplers *explicitly* declared static to uniform,
// which is incorrect but harmless.
- type.getQualifier().storage = EvqUniform;
+ declaredType.getQualifier().storage = EvqUniform;
} else {
- type.getQualifier().storage = EvqGlobal;
+ declaredType.getQualifier().storage = EvqGlobal;
}
}
HlslToken idToken;
while (acceptIdentifier(idToken)) {
// function_parameters
- TFunction& function = *new TFunction(idToken.string, type);
+ TFunction& function = *new TFunction(idToken.string, declaredType);
if (acceptFunctionParameters(function)) {
// post_decls
acceptPostDecls(function.getWritableType().getQualifier());
parseContext.handleFunctionDeclarator(idToken.loc, function, true);
}
} else {
- // a variable declaration
+ // A variable declaration.
+ // We can handle multiple variables per type declaration, so
+ // the number of types can expand when arrayness is different.
+ TType variableType;
+ variableType.shallowCopy(declaredType);
- // array_specifier
+ // recognize array_specifier
TArraySizes* arraySizes = nullptr;
acceptArraySpecifier(arraySizes);
+ // Fix arrayness in the variableType
+ if (declaredType.isImplicitlySizedArray()) {
+ // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
+ // of different sizes, for this case sharing the shallow copy of arrayness
+ // with the parseType oversubscribes it, so get a deep copy of the arrayness.
+ variableType.newArraySizes(declaredType.getArraySizes());
+ }
+ if (arraySizes || variableType.isArray()) {
+ // In the most general case, arrayness is potentially coming both from the
+ // declared type and from the variable: "int[] a[];" or just one or the other.
+ // Merge it all to the variableType, so all arrayness is part of the variableType.
+ parseContext.arrayDimMerge(variableType, arraySizes);
+ }
+
// samplers accept immediate sampler state
- if (type.getBasicType() == EbtSampler) {
+ if (variableType.getBasicType() == EbtSampler) {
if (! acceptSamplerState())
return false;
}
// post_decls
- acceptPostDecls(type.getQualifier());
+ acceptPostDecls(variableType.getQualifier());
// EQUAL assignment_expression
TIntermTyped* expressionNode = nullptr;
}
if (typedefDecl)
- parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes);
- else if (type.getBasicType() == EbtBlock)
- parseContext.declareBlock(idToken.loc, type, idToken.string);
+ parseContext.declareTypedef(idToken.loc, *idToken.string, variableType, arraySizes);
+ else if (variableType.getBasicType() == EbtBlock)
+ parseContext.declareBlock(idToken.loc, variableType, idToken.string);
else {
// Declare the variable and add any initializer code to the AST.
// The top-level node is always made into an aggregate, as that's
// historically how the AST has been.
node = intermediate.growAggregate(node,
- parseContext.declareVariable(idToken.loc, *idToken.string, type,
- arraySizes, expressionNode),
+ parseContext.declareVariable(idToken.loc, *idToken.string, variableType,
+ expressionNode),
idToken.loc);
}
}
return false;
}
- node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode);
+ node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
return true;
}
TType type;
type.deepCopy(parseType);
- // Arrayness is potentially coming both from the type and from the
- // variable: "int[] a[];" or just one or the other.
- // Merge it all to the type, so all arrayness is part of the type.
- arrayDimMerge(type, arraySizes);
-
TVariable* typeSymbol = new TVariable(&identifier, type, true);
if (! symbolTable.insert(*typeSymbol))
error(loc, "name already defined", "typedef", identifier.c_str());
// 'parseType' is the type part of the declaration (to the left)
// 'arraySizes' is the arrayness tagged on the identifier (to the right)
//
-TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes, TIntermTyped* initializer)
+TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, TType& type, TIntermTyped* initializer)
{
// TODO: things scoped within an annotation need their own name space;
// haven't done that yet
return nullptr;
// TODO: strings are not yet handled
- if (parseType.getBasicType() == EbtString)
+ if (type.getBasicType() == EbtString)
return nullptr;
- TType type;
- type.shallowCopy(parseType);
- if (type.isImplicitlySizedArray()) {
- // Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
- // of different sizes, for this case sharing the shallow copy of arrayness
- // with the parseType oversubscribes it, so get a deep copy of the arrayness.
- type.newArraySizes(*parseType.getArraySizes());
- }
-
if (voidErrorCheck(loc, identifier, type.getBasicType()))
return nullptr;
bool flattenVar = false;
// Declare the variable
- if (arraySizes || type.isArray()) {
- // Arrayness is potentially coming both from the type and from the
- // variable: "int[] a[];" or just one or the other.
- // Merge it all to the type, so all arrayness is part of the type.
- arrayDimMerge(type, arraySizes); // Safe if there are no arraySizes
-
+ if (type.isArray()) {
+ // array case
declareArray(loc, identifier, type, symbol, newDeclaration);
-
flattenVar = shouldFlatten(type);
-
if (flattenVar)
flatten(loc, *symbol->getAsVariable());
} else {
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0);
- TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
+ TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);