HLSL: Add typedef grammar and production.
diff --git a/Test/baseResults/hlsl.typedef.frag.out b/Test/baseResults/hlsl.typedef.frag.out
new file mode 100755
index 0000000..ca0235a
--- /dev/null
+++ b/Test/baseResults/hlsl.typedef.frag.out
@@ -0,0 +1,132 @@
+hlsl.typedef.frag
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:12  Function Definition: ShaderFunction(vf4;i1; (global 4-component vector of float)
+0:4    Function Parameters: 
+0:4      'input' (in 4-component vector of float)
+0:4      'ii' (in int)
+0:?     Sequence
+0:6      Sequence
+0:6        move second child to first child (temp 4-component vector of float)
+0:6          'a1' (temp 4-component vector of float)
+0:6          Constant:
+0:6            1.000000
+0:6            1.000000
+0:6            1.000000
+0:6            1.000000
+0:7      Sequence
+0:7        move second child to first child (temp int)
+0:7          'i' (temp int)
+0:7          Constant:
+0:7            2 (const int)
+0:9      Sequence
+0:9        move second child to first child (temp int)
+0:9          'j' (temp int)
+0:9          'ii' (in int)
+0:10      Branch: Return with expression
+0:10        add (temp 4-component vector of float)
+0:10          component-wise multiply (temp 4-component vector of float)
+0:10            'input' (in 4-component vector of float)
+0:10            'a1' (temp 4-component vector of float)
+0:10          Construct vec4 (global 4-component vector of float)
+0:10            Convert int to float (temp float)
+0:10              add (temp int)
+0:10                'i' (temp int)
+0:10                'j' (temp int)
+0:?   Linker Objects
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:12  Function Definition: ShaderFunction(vf4;i1; (global 4-component vector of float)
+0:4    Function Parameters: 
+0:4      'input' (in 4-component vector of float)
+0:4      'ii' (in int)
+0:?     Sequence
+0:6      Sequence
+0:6        move second child to first child (temp 4-component vector of float)
+0:6          'a1' (temp 4-component vector of float)
+0:6          Constant:
+0:6            1.000000
+0:6            1.000000
+0:6            1.000000
+0:6            1.000000
+0:7      Sequence
+0:7        move second child to first child (temp int)
+0:7          'i' (temp int)
+0:7          Constant:
+0:7            2 (const int)
+0:9      Sequence
+0:9        move second child to first child (temp int)
+0:9          'j' (temp int)
+0:9          'ii' (in int)
+0:10      Branch: Return with expression
+0:10        add (temp 4-component vector of float)
+0:10          component-wise multiply (temp 4-component vector of float)
+0:10            'input' (in 4-component vector of float)
+0:10            'a1' (temp 4-component vector of float)
+0:10          Construct vec4 (global 4-component vector of float)
+0:10            Convert int to float (temp float)
+0:10              add (temp int)
+0:10                'i' (temp int)
+0:10                'j' (temp int)
+0:?   Linker Objects
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 34
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "PixelShaderFunction"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 450
+                              Name 4  "PixelShaderFunction"
+                              Name 14  "ShaderFunction(vf4;i1;"
+                              Name 12  "input"
+                              Name 13  "ii"
+                              Name 16  "a1"
+                              Name 19  "i"
+                              Name 21  "j"
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Function 7(fvec4)
+               9:             TypeInt 32 1
+              10:             TypePointer Function 9(int)
+              11:             TypeFunction 7(fvec4) 8(ptr) 10(ptr)
+              17:    6(float) Constant 1065353216
+              18:    7(fvec4) ConstantComposite 17 17 17 17
+              20:      9(int) Constant 2
+4(PixelShaderFunction):           2 Function None 3
+               5:             Label
+                              FunctionEnd
+14(ShaderFunction(vf4;i1;):    7(fvec4) Function None 11
+       12(input):      8(ptr) FunctionParameter
+          13(ii):     10(ptr) FunctionParameter
+              15:             Label
+          16(a1):      8(ptr) Variable Function
+           19(i):     10(ptr) Variable Function
+           21(j):     10(ptr) Variable Function
+                              Store 16(a1) 18
+                              Store 19(i) 20
+              22:      9(int) Load 13(ii)
+                              Store 21(j) 22
+              23:    7(fvec4) Load 12(input)
+              24:    7(fvec4) Load 16(a1)
+              25:    7(fvec4) FMul 23 24
+              26:      9(int) Load 19(i)
+              27:      9(int) Load 21(j)
+              28:      9(int) IAdd 26 27
+              29:    6(float) ConvertSToF 28
+              30:    7(fvec4) CompositeConstruct 29 29 29 29
+              31:    7(fvec4) FAdd 25 30
+                              ReturnValue 31
+                              FunctionEnd
diff --git a/Test/hlsl.typedef.frag b/Test/hlsl.typedef.frag
new file mode 100644
index 0000000..b09785e
--- /dev/null
+++ b/Test/hlsl.typedef.frag
@@ -0,0 +1,11 @@
+typedef float4 myVec4;
+
+float4 ShaderFunction(float4 input, int ii) : COLOR0
+{
+    typedef int myInt;
+    myVec4 a1 = myVec4(1.0);
+    myInt i = 2;
+    typedef myInt myInt2;
+    myInt2 j = ii;
+    return input * a1 + myVec4(i + j);
+}
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 040739f..a004419 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -104,6 +104,7 @@
         {"hlsl.switch.frag", "PixelShaderFunction"},
         {"hlsl.swizzle.frag", "PixelShaderFunction"},
         {"hlsl.templatetypes.frag", "PixelShaderFunction"},
+        {"hlsl.typedef.frag", "PixelShaderFunction"},
         {"hlsl.whileLoop.frag", "PixelShaderFunction"},
         {"hlsl.void.frag", "PixelShaderFunction"},
     }),
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index d92debd..ee8ebf3 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -108,6 +108,7 @@
 // declaration
 //      : fully_specified_type declarator_list SEMICOLON
 //      | fully_specified_type identifier function_parameters post_decls compound_statement  // function definition
+//      | typedef declaration
 //
 // declarator_list
 //      : declarator COMMA declarator COMMA declarator...  // zero or more declarators
@@ -130,6 +131,9 @@
     node = nullptr;
     bool list = false;
 
+    // typedef
+    bool typedefDecl = acceptTokenClass(EHTokTypedef);
+
     // fully_specified_type
     TType type;
     if (! acceptFullySpecifiedType(type))
@@ -150,9 +154,14 @@
             if (peekTokenClass(EHTokLeftBrace)) {
                 if (list)
                     parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
+                if (typedefDecl)
+                    parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
                 return acceptFunctionDefinition(*function, node);
-            } else
+            } else {
+                if (typedefDecl)
+                    parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
                 parseContext.handleFunctionDeclarator(idToken.loc, *function, true);
+            }
         } else {
             // a variable declaration
 
@@ -166,19 +175,25 @@
             // EQUAL assignment_expression
             TIntermTyped* expressionNode = nullptr;
             if (acceptTokenClass(EHTokAssign)) {
+                if (typedefDecl)
+                    parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
                 if (! acceptAssignmentExpression(expressionNode)) {
                     expected("initializer");
                     return false;
                 }
             }
 
-            // 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),
-                                              idToken.loc);
+            if (typedefDecl)
+                parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes);
+            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),
+                                                  idToken.loc);
+            }
         }
 
         if (acceptTokenClass(EHTokComma)) {
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 22cd1f4..43f685c 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -3019,6 +3019,27 @@
 }
 
 //
+// Do everything necessary to handle a typedef declaration, for a single symbol.
+// 
+// 'parseType' is the type part of the declaration (to the left)
+// 'arraySizes' is the arrayness tagged on the identifier (to the right)
+//
+void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes)
+{
+    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());
+}
+
+//
 // Do everything necessary to handle a variable (non-block) declaration.
 // Either redeclaring a variable, or making a new one, updating the symbol
 // table, and all error checking.
@@ -3026,7 +3047,7 @@
 // Returns a subtree node that computes an initializer, if needed.
 // Returns nullptr if there is no code to execute for initialization.
 //
-// 'publicType' is the type part of the declaration (to the left)
+// '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)
@@ -3036,7 +3057,7 @@
     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 publicType oversubscribes it, so get a deep copy of the arrayness.
+        // with the parseType oversubscribes it, so get a deep copy of the arrayness.
         type.newArraySizes(*parseType.getArraySizes());
     }
 
@@ -3045,7 +3066,7 @@
 
     // Check for redeclaration of built-ins and/or attempting to declare a reserved name
     bool newDeclaration = false;    // true if a new entry gets added to the symbol table
-    TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers, newDeclaration);
+    TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), parseType.shaderQualifiers, newDeclaration);
 
     inheritGlobalDefaults(type.getQualifier());
 
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 5023371..9b3254d 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -126,6 +126,7 @@
     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
 
     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);
     TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
     TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);