From 82460b5e216acf81b28d52f2e8dc2d6bde74c7be Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Tue, 4 Apr 2017 11:47:42 -0600
Subject: [PATCH] HLSL: Fix #805: Support cast of scalars to structures.

Somewhat complex due to recognizing a general scalar, but not
replicating it for each member to avoid side effects.
---
 Test/baseResults/hlsl.scalarCast.vert.out | 501 ++++++++++++++++++++++
 Test/hlsl.scalarCast.vert                 |  37 ++
 glslang/Include/revision.h                |   2 +-
 gtests/Hlsl.FromFile.cpp                  |   1 +
 hlsl/hlslParseHelper.cpp                  | 109 +++--
 hlsl/hlslParseHelper.h                    |   7 +-
 6 files changed, 617 insertions(+), 40 deletions(-)
 create mode 100755 Test/baseResults/hlsl.scalarCast.vert.out
 create mode 100755 Test/hlsl.scalarCast.vert

diff --git a/Test/baseResults/hlsl.scalarCast.vert.out b/Test/baseResults/hlsl.scalarCast.vert.out
new file mode 100755
index 000000000..efb08b19f
--- /dev/null
+++ b/Test/baseResults/hlsl.scalarCast.vert.out
@@ -0,0 +1,501 @@
+hlsl.scalarCast.vert
+Shader version: 450
+0:? Sequence
+0:5  Function Definition: r0( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:5    Function Parameters: 
+0:?     Sequence
+0:7      Branch: Return with expression
+0:7        Constant:
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:9  Function Definition: r1( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:9    Function Parameters: 
+0:?     Sequence
+0:11      Branch: Return with expression
+0:11        Constant:
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:13  Function Definition: r2( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:13    Function Parameters: 
+0:?     Sequence
+0:15      Branch: Return with expression
+0:15        Constant:
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:17  Function Definition: r3( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:17    Function Parameters: 
+0:?     Sequence
+0:18      Sequence
+0:18        move second child to first child ( temp float)
+0:18          'f' ( temp float)
+0:18          Constant:
+0:18            2.000000
+0:19      Branch: Return with expression
+0:19        Construct structure ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:19          Construct vec4 ( temp 4-component vector of float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:19          Construct vec2 ( temp 2-component vector of float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:21  Function Definition: r4( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:21    Function Parameters: 
+0:?     Sequence
+0:22      Sequence
+0:22        move second child to first child ( temp float)
+0:22          'f' ( temp float)
+0:22          Constant:
+0:22            2.000000
+0:23      Branch: Return with expression
+0:23        Comma ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:23          move second child to first child ( temp float)
+0:23            'scalarCopy' ( temp float)
+0:23            add ( temp float)
+0:23              'f' ( temp float)
+0:23              Constant:
+0:23                1.000000
+0:23          Construct structure ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:23            Construct vec4 ( temp 4-component vector of float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:23            Construct vec2 ( temp 2-component vector of float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:25  Function Definition: r5( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:25    Function Parameters: 
+0:?     Sequence
+0:26      Sequence
+0:26        move second child to first child ( temp float)
+0:26          'f' ( temp float)
+0:26          Constant:
+0:26            2.000000
+0:27      Branch: Return with expression
+0:27        Comma ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:27          move second child to first child ( temp float)
+0:27            'scalarCopy' ( temp float)
+0:27            sine ( temp float)
+0:27              'f' ( temp float)
+0:27          Construct structure ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:27            Construct vec4 ( temp 4-component vector of float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:27            Construct vec2 ( temp 2-component vector of float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:29  Function Definition: @main( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29    Function Parameters: 
+0:?     Sequence
+0:30      Sequence
+0:30        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:30          'v0' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:30          Function Call: r0( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:31      Sequence
+0:31        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:31          'v1' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:31          Function Call: r1( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:32      Sequence
+0:32        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:32          'v2' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:32          Function Call: r2( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:33      Sequence
+0:33        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:33          'v3' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:33          Function Call: r3( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:34      Sequence
+0:34        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:34          'v4' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:34          Function Call: r4( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:35      Sequence
+0:35        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:35          'v5' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:35          Function Call: r5( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:36      Branch: Return with expression
+0:36        Constant:
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:29  Function Definition: main( ( temp void)
+0:29    Function Parameters: 
+0:?     Sequence
+0:29      Sequence
+0:29        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29          'flattenTemp' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29          Function Call: @main( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29        move second child to first child ( temp 4-component vector of float)
+0:?           '@entryPointOutput_position' ( out 4-component vector of float Position)
+0:29          position: direct index for structure ( temp 4-component vector of float)
+0:29            'flattenTemp' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29            Constant:
+0:29              0 (const int)
+0:29        move second child to first child ( temp 2-component vector of float)
+0:29          texCoord: direct index for structure ( temp 2-component vector of float)
+0:29            '@entryPointOutput' (layout( location=0) out structure{ temp 2-component vector of float texCoord})
+0:29            Constant:
+0:29              0 (const int)
+0:29          texCoord: direct index for structure ( temp 2-component vector of float)
+0:29            'flattenTemp' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29            Constant:
+0:29              1 (const int)
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out structure{ temp 2-component vector of float texCoord})
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+0:? Sequence
+0:5  Function Definition: r0( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:5    Function Parameters: 
+0:?     Sequence
+0:7      Branch: Return with expression
+0:7        Constant:
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:7          2.000000
+0:9  Function Definition: r1( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:9    Function Parameters: 
+0:?     Sequence
+0:11      Branch: Return with expression
+0:11        Constant:
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:11          3.000000
+0:13  Function Definition: r2( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:13    Function Parameters: 
+0:?     Sequence
+0:15      Branch: Return with expression
+0:15        Constant:
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:15          0.909297
+0:17  Function Definition: r3( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:17    Function Parameters: 
+0:?     Sequence
+0:18      Sequence
+0:18        move second child to first child ( temp float)
+0:18          'f' ( temp float)
+0:18          Constant:
+0:18            2.000000
+0:19      Branch: Return with expression
+0:19        Construct structure ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:19          Construct vec4 ( temp 4-component vector of float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:19          Construct vec2 ( temp 2-component vector of float)
+0:19            'f' ( temp float)
+0:19            'f' ( temp float)
+0:21  Function Definition: r4( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:21    Function Parameters: 
+0:?     Sequence
+0:22      Sequence
+0:22        move second child to first child ( temp float)
+0:22          'f' ( temp float)
+0:22          Constant:
+0:22            2.000000
+0:23      Branch: Return with expression
+0:23        Comma ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:23          move second child to first child ( temp float)
+0:23            'scalarCopy' ( temp float)
+0:23            add ( temp float)
+0:23              'f' ( temp float)
+0:23              Constant:
+0:23                1.000000
+0:23          Construct structure ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:23            Construct vec4 ( temp 4-component vector of float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:23            Construct vec2 ( temp 2-component vector of float)
+0:23              'scalarCopy' ( temp float)
+0:23              'scalarCopy' ( temp float)
+0:25  Function Definition: r5( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:25    Function Parameters: 
+0:?     Sequence
+0:26      Sequence
+0:26        move second child to first child ( temp float)
+0:26          'f' ( temp float)
+0:26          Constant:
+0:26            2.000000
+0:27      Branch: Return with expression
+0:27        Comma ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:27          move second child to first child ( temp float)
+0:27            'scalarCopy' ( temp float)
+0:27            sine ( temp float)
+0:27              'f' ( temp float)
+0:27          Construct structure ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:27            Construct vec4 ( temp 4-component vector of float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:27            Construct vec2 ( temp 2-component vector of float)
+0:27              'scalarCopy' ( temp float)
+0:27              'scalarCopy' ( temp float)
+0:29  Function Definition: @main( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29    Function Parameters: 
+0:?     Sequence
+0:30      Sequence
+0:30        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:30          'v0' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:30          Function Call: r0( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:31      Sequence
+0:31        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:31          'v1' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:31          Function Call: r1( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:32      Sequence
+0:32        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:32          'v2' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:32          Function Call: r2( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:33      Sequence
+0:33        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:33          'v3' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:33          Function Call: r3( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:34      Sequence
+0:34        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:34          'v4' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:34          Function Call: r4( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:35      Sequence
+0:35        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:35          'v5' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:35          Function Call: r5( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:36      Branch: Return with expression
+0:36        Constant:
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:36          1.000000
+0:29  Function Definition: main( ( temp void)
+0:29    Function Parameters: 
+0:?     Sequence
+0:29      Sequence
+0:29        move second child to first child ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29          'flattenTemp' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29          Function Call: @main( ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29        move second child to first child ( temp 4-component vector of float)
+0:?           '@entryPointOutput_position' ( out 4-component vector of float Position)
+0:29          position: direct index for structure ( temp 4-component vector of float)
+0:29            'flattenTemp' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29            Constant:
+0:29              0 (const int)
+0:29        move second child to first child ( temp 2-component vector of float)
+0:29          texCoord: direct index for structure ( temp 2-component vector of float)
+0:29            '@entryPointOutput' (layout( location=0) out structure{ temp 2-component vector of float texCoord})
+0:29            Constant:
+0:29              0 (const int)
+0:29          texCoord: direct index for structure ( temp 2-component vector of float)
+0:29            'flattenTemp' ( temp structure{ temp 4-component vector of float position,  temp 2-component vector of float texCoord})
+0:29            Constant:
+0:29              1 (const int)
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out structure{ temp 2-component vector of float texCoord})
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 123
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 108 116
+                              Name 4  "main"
+                              Name 9  "VertexOut"
+                              MemberName 9(VertexOut) 0  "position"
+                              MemberName 9(VertexOut) 1  "texCoord"
+                              Name 11  "r0("
+                              Name 13  "r1("
+                              Name 15  "r2("
+                              Name 17  "r3("
+                              Name 19  "r4("
+                              Name 21  "r5("
+                              Name 23  "@main("
+                              Name 44  "f"
+                              Name 56  "f"
+                              Name 57  "scalarCopy"
+                              Name 72  "f"
+                              Name 73  "scalarCopy"
+                              Name 88  "v0"
+                              Name 90  "v1"
+                              Name 92  "v2"
+                              Name 94  "v3"
+                              Name 96  "v4"
+                              Name 98  "v5"
+                              Name 105  "flattenTemp"
+                              Name 108  "@entryPointOutput_position"
+                              Name 114  "VertexOut"
+                              MemberName 114(VertexOut) 0  "texCoord"
+                              Name 116  "@entryPointOutput"
+                              Decorate 108(@entryPointOutput_position) BuiltIn Position
+                              Decorate 116(@entryPointOutput) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeVector 6(float) 2
+    9(VertexOut):             TypeStruct 7(fvec4) 8(fvec2)
+              10:             TypeFunction 9(VertexOut)
+              25:    6(float) Constant 1073741824
+              26:    7(fvec4) ConstantComposite 25 25 25 25
+              27:    8(fvec2) ConstantComposite 25 25
+              28:9(VertexOut) ConstantComposite 26 27
+              31:    6(float) Constant 1077936128
+              32:    7(fvec4) ConstantComposite 31 31 31 31
+              33:    8(fvec2) ConstantComposite 31 31
+              34:9(VertexOut) ConstantComposite 32 33
+              37:    6(float) Constant 1063831479
+              38:    7(fvec4) ConstantComposite 37 37 37 37
+              39:    8(fvec2) ConstantComposite 37 37
+              40:9(VertexOut) ConstantComposite 38 39
+              43:             TypePointer Function 6(float)
+              59:    6(float) Constant 1065353216
+              87:             TypePointer Function 9(VertexOut)
+             100:    7(fvec4) ConstantComposite 59 59 59 59
+             101:    8(fvec2) ConstantComposite 59 59
+             102:9(VertexOut) ConstantComposite 100 101
+             107:             TypePointer Output 7(fvec4)
+108(@entryPointOutput_position):    107(ptr) Variable Output
+             109:             TypeInt 32 1
+             110:    109(int) Constant 0
+             111:             TypePointer Function 7(fvec4)
+  114(VertexOut):             TypeStruct 8(fvec2)
+             115:             TypePointer Output 114(VertexOut)
+116(@entryPointOutput):    115(ptr) Variable Output
+             117:    109(int) Constant 1
+             118:             TypePointer Function 8(fvec2)
+             121:             TypePointer Output 8(fvec2)
+         4(main):           2 Function None 3
+               5:             Label
+105(flattenTemp):     87(ptr) Variable Function
+             106:9(VertexOut) FunctionCall 23(@main()
+                              Store 105(flattenTemp) 106
+             112:    111(ptr) AccessChain 105(flattenTemp) 110
+             113:    7(fvec4) Load 112
+                              Store 108(@entryPointOutput_position) 113
+             119:    118(ptr) AccessChain 105(flattenTemp) 117
+             120:    8(fvec2) Load 119
+             122:    121(ptr) AccessChain 116(@entryPointOutput) 110
+                              Store 122 120
+                              Return
+                              FunctionEnd
+         11(r0():9(VertexOut) Function None 10
+              12:             Label
+                              ReturnValue 28
+                              FunctionEnd
+         13(r1():9(VertexOut) Function None 10
+              14:             Label
+                              ReturnValue 34
+                              FunctionEnd
+         15(r2():9(VertexOut) Function None 10
+              16:             Label
+                              ReturnValue 40
+                              FunctionEnd
+         17(r3():9(VertexOut) Function None 10
+              18:             Label
+           44(f):     43(ptr) Variable Function
+                              Store 44(f) 25
+              45:    6(float) Load 44(f)
+              46:    6(float) Load 44(f)
+              47:    6(float) Load 44(f)
+              48:    6(float) Load 44(f)
+              49:    7(fvec4) CompositeConstruct 45 46 47 48
+              50:    6(float) Load 44(f)
+              51:    6(float) Load 44(f)
+              52:    8(fvec2) CompositeConstruct 50 51
+              53:9(VertexOut) CompositeConstruct 49 52
+                              ReturnValue 53
+                              FunctionEnd
+         19(r4():9(VertexOut) Function None 10
+              20:             Label
+           56(f):     43(ptr) Variable Function
+  57(scalarCopy):     43(ptr) Variable Function
+                              Store 56(f) 25
+              58:    6(float) Load 56(f)
+              60:    6(float) FAdd 58 59
+                              Store 57(scalarCopy) 60
+              61:    6(float) Load 57(scalarCopy)
+              62:    6(float) Load 57(scalarCopy)
+              63:    6(float) Load 57(scalarCopy)
+              64:    6(float) Load 57(scalarCopy)
+              65:    7(fvec4) CompositeConstruct 61 62 63 64
+              66:    6(float) Load 57(scalarCopy)
+              67:    6(float) Load 57(scalarCopy)
+              68:    8(fvec2) CompositeConstruct 66 67
+              69:9(VertexOut) CompositeConstruct 65 68
+                              ReturnValue 69
+                              FunctionEnd
+         21(r5():9(VertexOut) Function None 10
+              22:             Label
+           72(f):     43(ptr) Variable Function
+  73(scalarCopy):     43(ptr) Variable Function
+                              Store 72(f) 25
+              74:    6(float) Load 72(f)
+              75:    6(float) ExtInst 1(GLSL.std.450) 13(Sin) 74
+                              Store 73(scalarCopy) 75
+              76:    6(float) Load 73(scalarCopy)
+              77:    6(float) Load 73(scalarCopy)
+              78:    6(float) Load 73(scalarCopy)
+              79:    6(float) Load 73(scalarCopy)
+              80:    7(fvec4) CompositeConstruct 76 77 78 79
+              81:    6(float) Load 73(scalarCopy)
+              82:    6(float) Load 73(scalarCopy)
+              83:    8(fvec2) CompositeConstruct 81 82
+              84:9(VertexOut) CompositeConstruct 80 83
+                              ReturnValue 84
+                              FunctionEnd
+      23(@main():9(VertexOut) Function None 10
+              24:             Label
+          88(v0):     87(ptr) Variable Function
+          90(v1):     87(ptr) Variable Function
+          92(v2):     87(ptr) Variable Function
+          94(v3):     87(ptr) Variable Function
+          96(v4):     87(ptr) Variable Function
+          98(v5):     87(ptr) Variable Function
+              89:9(VertexOut) FunctionCall 11(r0()
+                              Store 88(v0) 89
+              91:9(VertexOut) FunctionCall 13(r1()
+                              Store 90(v1) 91
+              93:9(VertexOut) FunctionCall 15(r2()
+                              Store 92(v2) 93
+              95:9(VertexOut) FunctionCall 17(r3()
+                              Store 94(v3) 95
+              97:9(VertexOut) FunctionCall 19(r4()
+                              Store 96(v4) 97
+              99:9(VertexOut) FunctionCall 21(r5()
+                              Store 98(v5) 99
+                              ReturnValue 102
+                              FunctionEnd
diff --git a/Test/hlsl.scalarCast.vert b/Test/hlsl.scalarCast.vert
new file mode 100755
index 000000000..83bfd6eb2
--- /dev/null
+++ b/Test/hlsl.scalarCast.vert
@@ -0,0 +1,37 @@
+struct VertexOut {
+    float4 position : SV_Position;
+    float2 texCoord : TEXCOORD;
+};
+VertexOut r0() {
+    const float f = 2.0;
+    return (VertexOut)f;
+}
+VertexOut r1() {
+    const float f = 2.0;
+    return (VertexOut)(f + 1.0);
+}
+VertexOut r2() {
+    const float f = 2.0;
+    return (VertexOut)(sin(f));
+}
+VertexOut r3() {
+    float f = 2.0;
+    return (VertexOut)f;
+}
+VertexOut r4() {
+    float f = 2.0;
+    return (VertexOut)(f + 1.0);
+}
+VertexOut r5() {
+    float f = 2.0;
+    return (VertexOut)(sin(f));
+}
+VertexOut main() {
+    VertexOut v0 = r0();
+    VertexOut v1 = r1();
+    VertexOut v2 = r2();
+    VertexOut v3 = r3();
+    VertexOut v4 = r4();
+    VertexOut v5 = r5();
+    return (VertexOut)1;
+}
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index df5bcfee7..0b72b5b1e 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -3,4 +3,4 @@
 // For the date, it uses the current date (when then script is run).
 
 #define GLSLANG_REVISION "Overload400-PrecQual.1971"
-#define GLSLANG_DATE "03-Apr-2017"
+#define GLSLANG_DATE "04-Apr-2017"
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index bcc1084d3..6bad94e2f 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -223,6 +223,7 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.samplelevel.offsetarray.dx10.frag", "main"},
         {"hlsl.sample.sub-vec4.dx10.frag", "main"},
         {"hlsl.scalar-length.frag", "main"},
+        {"hlsl.scalarCast.vert", "main"},
         {"hlsl.semicolons.frag", "main"},
         {"hlsl.shapeConv.frag", "main"},
         {"hlsl.shapeConvRet.frag", "main"},
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 397cf8920..df67d1e9e 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -335,13 +335,6 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
                            [](bool isSet) { return isSet; } );
     };
 
-    // helper to create a temporary variable
-    const auto addTmpVar = [&](const char* name, const TType& derefType) -> TIntermSymbol* {
-        TVariable* tmpVar = makeInternalVariable(name, derefType);
-        tmpVar->getWritableType().getQualifier().makeTemporary();
-        return intermediate.addSymbol(*tmpVar, loc);
-    };
-
     // Create swizzle matching input swizzle
     const auto addSwizzle = [&](TIntermSymbol* var, TIntermBinary* swizzle) -> TIntermTyped* {
         if (swizzle)
@@ -419,7 +412,7 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
                 TIntermTyped* coordTmp = coord;
 
                 if (rhsTmp == nullptr || isModifyOp || lhsIsSwizzle) {
-                    rhsTmp = addTmpVar("storeTemp", objDerefType);
+                    rhsTmp = makeInternalVariableNode(loc, "storeTemp", objDerefType);
 
                     // Partial updates not yet supported
                     if (!writesAllComponents(rhsTmp, lhsAsBinary)) {
@@ -429,7 +422,7 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
                     // Assign storeTemp = rhs
                     if (isModifyOp) {
                         // We have to make a temp var for the coordinate, to avoid evaluating it twice.
-                        coordTmp = addTmpVar("coordTemp", coord->getType());
+                        coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType());
                         makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1]
                         makeLoad(rhsTmp, object, coordTmp, objDerefType); // rhsTmp = OpImageLoad(object, coordTmp)
                     }
@@ -462,8 +455,8 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
                 //      OpImageStore(object, coordTmp, rhsTmp)
                 //      rhsTmp
 
-                TIntermSymbol* rhsTmp = addTmpVar("storeTemp", objDerefType);
-                TIntermTyped* coordTmp = addTmpVar("coordTemp", coord->getType());
+                TIntermSymbol* rhsTmp = makeInternalVariableNode(loc, "storeTemp", objDerefType);
+                TIntermTyped* coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType());
 
                 makeBinary(EOpAssign, coordTmp, coord);           // coordtmp = load[param1]
                 makeLoad(rhsTmp, object, coordTmp, objDerefType); // rhsTmp = OpImageLoad(object, coordTmp)
@@ -483,9 +476,9 @@ TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char*
                 //      rhsTmp2 op
                 //      OpImageStore(object, coordTmp, rhsTmp2)
                 //      rhsTmp1 (pre-op value)
-                TIntermSymbol* rhsTmp1 = addTmpVar("storeTempPre",  objDerefType);
-                TIntermSymbol* rhsTmp2 = addTmpVar("storeTempPost", objDerefType);
-                TIntermTyped* coordTmp = addTmpVar("coordTemp", coord->getType());
+                TIntermSymbol* rhsTmp1 = makeInternalVariableNode(loc, "storeTempPre",  objDerefType);
+                TIntermSymbol* rhsTmp2 = makeInternalVariableNode(loc, "storeTempPost", objDerefType);
+                TIntermTyped* coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType());
 
                 makeBinary(EOpAssign, coordTmp, coord);            // coordtmp = load[param1]
                 makeLoad(rhsTmp1, object, coordTmp, objDerefType); // rhsTmp1 = OpImageLoad(object, coordTmp)
@@ -4739,7 +4732,7 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
         return true;
     }
 
-    if (op == EOpConstructStruct && ! type.isArray() && isZeroConstructor(node))
+    if (op == EOpConstructStruct && ! type.isArray() && isScalarConstructor(node))
         return false;
 
     if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) {
@@ -4756,10 +4749,21 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
     return false;
 }
 
-bool HlslParseContext::isZeroConstructor(const TIntermNode* node)
+// See if 'node', in the context of constructing aggregates, is a scalar argument
+// to a constructor.
+//
+bool HlslParseContext::isScalarConstructor(const TIntermNode* node)
 {
-    return node->getAsTyped()->isScalar() && node->getAsConstantUnion() &&
-           node->getAsConstantUnion()->getConstArray()[0].getIConst() == 0;
+    // Obviously, it must be a scalar, but an aggregate node might not be fully
+    // completed yet: holding a sequence of initializers under an aggregate
+    // would not yet be typed, so don't check it's type.  This corresponds to
+    // the aggregate operator also not being set yet. (An aggregate operation
+    // that legitimately yields a scalar will have a getOp() of that operator,
+    // not EOpNull.)
+
+    return node->getAsTyped() != nullptr &&
+           node->getAsTyped()->isScalar() &&
+           (node->getAsAggregate() == nullptr || node->getAsAggregate()->getOp() != EOpNull);
 }
 
 // Verify all the correct semantics for constructing a combined texture/sampler.
@@ -6295,6 +6299,15 @@ TVariable* HlslParseContext::makeInternalVariable(const char* name, const TType&
     return variable;
 }
 
+// Make a symbol node holding a new internal temporary variable.
+TIntermSymbol* HlslParseContext::makeInternalVariableNode(const TSourceLoc& loc, const char* name, const TType& type) const
+{
+    TVariable* tmpVar = makeInternalVariable(name, type);
+    tmpVar->getWritableType().getQualifier().makeTemporary();
+
+    return intermediate.addSymbol(*tmpVar, loc);
+}
+
 //
 // Declare a non-array variable, the main point being there is no redeclaration
 // for resizing allowed.
@@ -6345,7 +6358,7 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
     skeletalType.shallowCopy(variable->getType());
     skeletalType.getQualifier().makeTemporary();
     if (initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull)
-        initializer = convertInitializerList(loc, skeletalType, initializer);
+        initializer = convertInitializerList(loc, skeletalType, initializer, nullptr);
     if (! initializer) {
         // error recovery; don't leave const without constant values
         if (qualifier == EvqConst)
@@ -6427,7 +6440,8 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
 //
 // Returns nullptr if there is an error.
 //
-TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer)
+TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type,
+                                                       TIntermTyped* initializer, TIntermTyped* scalarInit)
 {
     // Will operate recursively.  Once a subtree is found that is constructor style,
     // everything below it is already good: Only the "top part" of the initializer
@@ -6473,12 +6487,12 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
         }
 
         // lengthen list to be long enough
-        lengthenList(loc, initList->getSequence(), arrayType.getOuterArraySize());
+        lengthenList(loc, initList->getSequence(), arrayType.getOuterArraySize(), scalarInit);
 
         // recursively process each element
         TType elementType(arrayType, 0); // dereferenced type
         for (int i = 0; i < arrayType.getOuterArraySize(); ++i) {
-            initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped());
+            initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped(), scalarInit);
             if (initList->getSequence()[i] == nullptr)
                 return nullptr;
         }
@@ -6486,14 +6500,14 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
         return addConstructor(loc, initList, arrayType);
     } else if (type.isStruct()) {
         // lengthen list to be long enough
-        lengthenList(loc, initList->getSequence(), static_cast<int>(type.getStruct()->size()));
+        lengthenList(loc, initList->getSequence(), static_cast<int>(type.getStruct()->size()), scalarInit);
 
         if (type.getStruct()->size() != initList->getSequence().size()) {
             error(loc, "wrong number of structure members", "initializer list", "");
             return nullptr;
         }
         for (size_t i = 0; i < type.getStruct()->size(); ++i) {
-            initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped());
+            initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped(), scalarInit);
             if (initList->getSequence()[i] == nullptr)
                 return nullptr;
         }
@@ -6504,7 +6518,7 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
             // a constructor; no further processing needed.
         } else {
             // lengthen list to be long enough
-            lengthenList(loc, initList->getSequence(), type.getMatrixCols());
+            lengthenList(loc, initList->getSequence(), type.getMatrixCols(), scalarInit);
 
             if (type.getMatrixCols() != (int)initList->getSequence().size()) {
                 error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str());
@@ -6512,14 +6526,14 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
             }
             TType vectorType(type, 0); // dereferenced type
             for (int i = 0; i < type.getMatrixCols(); ++i) {
-                initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped());
+                initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped(), scalarInit);
                 if (initList->getSequence()[i] == nullptr)
                     return nullptr;
             }
         }
     } else if (type.isVector()) {
         // lengthen list to be long enough
-        lengthenList(loc, initList->getSequence(), type.getVectorSize());
+        lengthenList(loc, initList->getSequence(), type.getVectorSize(), scalarInit);
 
         // error check; we're at bottom, so work is finished below
         if (type.getVectorSize() != (int)initList->getSequence().size()) {
@@ -6528,7 +6542,7 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
         }
     } else if (type.isScalar()) {
         // lengthen list to be long enough
-        lengthenList(loc, initList->getSequence(), 1);
+        lengthenList(loc, initList->getSequence(), 1, scalarInit);
 
         if ((int)initList->getSequence().size() != 1) {
             error(loc, "scalar expected one element:", "initializer list", type.getCompleteString().c_str());
@@ -6553,10 +6567,21 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
 // Lengthen list to be long enough to cover any gap from the current list size
 // to 'size'. If the list is longer, do nothing.
 // The value to lengthen with is the default for short lists.
-void HlslParseContext::lengthenList(const TSourceLoc& loc, TIntermSequence& list, int size)
+//
+// By default, lists that are too short due to lack of initializers initialize to zero.
+// Alternatively, it could be a scalar initializer for a structure. Both cases are handled,
+// based on whether something is passed in as 'scalarInit'.
+//
+// 'scalarInit' must be safe to use each time this is called (no side effects replication).
+//
+void HlslParseContext::lengthenList(const TSourceLoc& loc, TIntermSequence& list, int size, TIntermTyped* scalarInit)
 {
-    for (int c = (int)list.size(); c < size; ++c)
-        list.push_back(intermediate.addConstantUnion(0, loc));
+    for (int c = (int)list.size(); c < size; ++c) {
+        if (scalarInit == nullptr)
+            list.push_back(intermediate.addConstantUnion(0, loc));
+        else
+            list.push_back(scalarInit);
+    }
 }
 
 //
@@ -6570,11 +6595,23 @@ TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TInterm
     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));
+    // Handle the idiom "(struct type)<scalar value>"
+    if (type.isStruct() && isScalarConstructor(node)) {
+        // 'node' will almost always get used multiple times, so should not be used directly,
+        // it would create a DAG instead of a tree, which might be okay (would
+        // like to formalize that for constants and symbols), but if it has
+        // side effects, they would get executed multiple times, which is not okay.
+        if (node->getAsConstantUnion() == nullptr && node->getAsSymbolNode() == nullptr) {
+            TIntermAggregate* seq = intermediate.makeAggregate(loc);
+            TIntermSymbol* copy = makeInternalVariableNode(loc, "scalarCopy", node->getType());
+            seq = intermediate.growAggregate(seq, intermediate.addBinaryNode(EOpAssign, copy, node, loc));
+            seq = intermediate.growAggregate(seq, convertInitializerList(loc, type, intermediate.makeAggregate(loc), copy));
+            seq->setOp(EOpComma);
+            seq->setType(type);
+            return seq;
+        } else
+            return convertInitializerList(loc, type, intermediate.makeAggregate(loc), node);
+    }
 
     return addConstructor(loc, node, type);
 }
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 75468434d..7fd06e9fb 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -140,7 +140,7 @@ public:
     void declareStruct(const TSourceLoc&, TString& structName, TType&);
     TSymbol* lookupUserType(const TString&, TType&);
     TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = 0);
-    void lengthenList(const TSourceLoc&, TIntermSequence& list, int size);
+    void lengthenList(const TSourceLoc&, TIntermSequence& list, int size, TIntermTyped* scalarInit);
     TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
     TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&);
     TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
@@ -217,11 +217,12 @@ protected:
     TVariable* makeInternalVariable(const TString& name, const TType& type) const {
         return makeInternalVariable(name.c_str(), type);
     }
+    TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const;
     TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track);
     void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track);
     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
-    TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
-    bool isZeroConstructor(const TIntermNode*);
+    TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit);
+    bool isScalarConstructor(const TIntermNode*);
     TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
 
     // Return true if this node requires L-value conversion (e.g, to an imageStore).
-- 
GitLab