Home | History | Annotate | Download | only in val
      1 // Copyright (c) 2017 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <sstream>
     16 #include <string>
     17 
     18 #include "gmock/gmock.h"
     19 #include "test/unit_spirv.h"
     20 #include "test/val/val_fixtures.h"
     21 
     22 namespace spvtools {
     23 namespace val {
     24 namespace {
     25 
     26 using ::testing::HasSubstr;
     27 using ::testing::Not;
     28 
     29 using ValidateComposites = spvtest::ValidateBase<bool>;
     30 
     31 std::string GenerateShaderCode(
     32     const std::string& body,
     33     const std::string& capabilities_and_extensions = "",
     34     const std::string& execution_model = "Fragment") {
     35   std::ostringstream ss;
     36   ss << R"(
     37 OpCapability Shader
     38 OpCapability Float64
     39 )";
     40 
     41   ss << capabilities_and_extensions;
     42   ss << "OpMemoryModel Logical GLSL450\n";
     43   ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
     44   if (execution_model == "Fragment") {
     45     ss << "OpExecutionMode %main OriginUpperLeft\n";
     46   }
     47 
     48   ss << R"(
     49 %void = OpTypeVoid
     50 %func = OpTypeFunction %void
     51 %bool = OpTypeBool
     52 %f32 = OpTypeFloat 32
     53 %f64 = OpTypeFloat 64
     54 %u32 = OpTypeInt 32 0
     55 %s32 = OpTypeInt 32 1
     56 %f32vec2 = OpTypeVector %f32 2
     57 %f32vec3 = OpTypeVector %f32 3
     58 %f32vec4 = OpTypeVector %f32 4
     59 %f64vec2 = OpTypeVector %f64 2
     60 %u32vec2 = OpTypeVector %u32 2
     61 %u32vec4 = OpTypeVector %u32 4
     62 %f64mat22 = OpTypeMatrix %f64vec2 2
     63 %f32mat22 = OpTypeMatrix %f32vec2 2
     64 %f32mat23 = OpTypeMatrix %f32vec2 3
     65 %f32mat32 = OpTypeMatrix %f32vec3 2
     66 
     67 %f32_0 = OpConstant %f32 0
     68 %f32_1 = OpConstant %f32 1
     69 %f32_2 = OpConstant %f32 2
     70 %f32_3 = OpConstant %f32 3
     71 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
     72 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
     73 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
     74 
     75 %u32_0 = OpConstant %u32 0
     76 %u32_1 = OpConstant %u32 1
     77 %u32_2 = OpConstant %u32 2
     78 %u32_3 = OpConstant %u32 3
     79 
     80 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
     81 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
     82 
     83 %f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
     84 %f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
     85 
     86 %f32vec2arr3 = OpTypeArray %f32vec2 %u32_3
     87 %f32vec2rarr = OpTypeRuntimeArray %f32vec2
     88 
     89 %f32u32struct = OpTypeStruct %f32 %u32
     90 %big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2rarr %f32u32struct
     91 
     92 %ptr_big_struct = OpTypePointer Uniform %big_struct
     93 %var_big_struct = OpVariable %ptr_big_struct Uniform
     94 
     95 %main = OpFunction %void None %func
     96 %main_entry = OpLabel
     97 )";
     98 
     99   ss << body;
    100 
    101   ss << R"(
    102 OpReturn
    103 OpFunctionEnd)";
    104 
    105   return ss.str();
    106 }
    107 
    108 // Returns header for legacy tests taken from val_id_test.cpp.
    109 std::string GetHeaderForTestsFromValId() {
    110   return R"(
    111 OpCapability Shader
    112 OpCapability Linkage
    113 OpCapability Addresses
    114 OpCapability Pipes
    115 OpCapability LiteralSampler
    116 OpCapability DeviceEnqueue
    117 OpCapability Vector16
    118 OpCapability Int8
    119 OpCapability Int16
    120 OpCapability Int64
    121 OpCapability Float64
    122 OpMemoryModel Logical GLSL450
    123 %void = OpTypeVoid
    124 %void_f  = OpTypeFunction %void
    125 %int = OpTypeInt 32 0
    126 %float = OpTypeFloat 32
    127 %v3float = OpTypeVector %float 3
    128 %mat4x3 = OpTypeMatrix %v3float 4
    129 %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
    130 %_ptr_Private_float = OpTypePointer Private %float
    131 %my_matrix = OpVariable %_ptr_Private_mat4x3 Private
    132 %my_float_var = OpVariable %_ptr_Private_float Private
    133 %_ptr_Function_float = OpTypePointer Function %float
    134 %int_0 = OpConstant %int 0
    135 %int_1 = OpConstant %int 1
    136 %int_2 = OpConstant %int 2
    137 %int_3 = OpConstant %int 3
    138 %int_5 = OpConstant %int 5
    139 
    140 ; Making the following nested structures.
    141 ;
    142 ; struct S {
    143 ;   bool b;
    144 ;   vec4 v[5];
    145 ;   int i;
    146 ;   mat4x3 m[5];
    147 ; }
    148 ; uniform blockName {
    149 ;   S s;
    150 ;   bool cond;
    151 ;   RunTimeArray arr;
    152 ; }
    153 
    154 %f32arr = OpTypeRuntimeArray %float
    155 %v4float = OpTypeVector %float 4
    156 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
    157 %array5_vec4 = OpTypeArray %v4float %int_5
    158 %_ptr_Uniform_float = OpTypePointer Uniform %float
    159 %_ptr_Function_vec4 = OpTypePointer Function %v4float
    160 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
    161 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
    162 %struct_blockName = OpTypeStruct %struct_s %int %f32arr
    163 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
    164 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
    165 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
    166 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
    167 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
    168 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
    169 %spec_int = OpSpecConstant %int 2
    170 %func = OpFunction %void None %void_f
    171 %my_label = OpLabel
    172 )";
    173 }
    174 
    175 TEST_F(ValidateComposites, VectorExtractDynamicSuccess) {
    176   const std::string body = R"(
    177 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0
    178 )";
    179 
    180   CompileSuccessfully(GenerateShaderCode(body).c_str());
    181   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    182 }
    183 
    184 TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) {
    185   const std::string body = R"(
    186 %val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0
    187 )";
    188 
    189   CompileSuccessfully(GenerateShaderCode(body).c_str());
    190   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    191   EXPECT_THAT(getDiagnosticString(),
    192               HasSubstr("Expected Result Type to be a scalar type"));
    193 }
    194 
    195 TEST_F(ValidateComposites, VectorExtractDynamicNotVector) {
    196   const std::string body = R"(
    197 %val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0
    198 )";
    199 
    200   CompileSuccessfully(GenerateShaderCode(body).c_str());
    201   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    202   EXPECT_THAT(getDiagnosticString(),
    203               HasSubstr("Expected Vector type to be OpTypeVector"));
    204 }
    205 
    206 TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) {
    207   const std::string body = R"(
    208 %val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0
    209 )";
    210 
    211   CompileSuccessfully(GenerateShaderCode(body).c_str());
    212   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    213   EXPECT_THAT(
    214       getDiagnosticString(),
    215       HasSubstr("Expected Vector component type to be equal to Result Type"));
    216 }
    217 
    218 TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) {
    219   const std::string body = R"(
    220 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0
    221 )";
    222 
    223   CompileSuccessfully(GenerateShaderCode(body).c_str());
    224   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    225   EXPECT_THAT(getDiagnosticString(),
    226               HasSubstr("Expected Index to be int scalar"));
    227 }
    228 
    229 TEST_F(ValidateComposites, VectorInsertDynamicSuccess) {
    230   const std::string body = R"(
    231 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0
    232 )";
    233 
    234   CompileSuccessfully(GenerateShaderCode(body).c_str());
    235   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    236 }
    237 
    238 TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) {
    239   const std::string body = R"(
    240 %val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0
    241 )";
    242 
    243   CompileSuccessfully(GenerateShaderCode(body).c_str());
    244   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    245   EXPECT_THAT(getDiagnosticString(),
    246               HasSubstr("Expected Result Type to be OpTypeVector"));
    247 }
    248 
    249 TEST_F(ValidateComposites, VectorInsertDynamicNotVector) {
    250   const std::string body = R"(
    251 %val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0
    252 )";
    253 
    254   CompileSuccessfully(GenerateShaderCode(body).c_str());
    255   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    256   EXPECT_THAT(getDiagnosticString(),
    257               HasSubstr("Expected Vector type to be equal to Result Type"));
    258 }
    259 
    260 TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) {
    261   const std::string body = R"(
    262 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0
    263 )";
    264 
    265   CompileSuccessfully(GenerateShaderCode(body).c_str());
    266   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    267   EXPECT_THAT(getDiagnosticString(),
    268               HasSubstr("Expected Component type to be equal to Result Type "
    269                         "component type"));
    270 }
    271 
    272 TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) {
    273   const std::string body = R"(
    274 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0
    275 )";
    276 
    277   CompileSuccessfully(GenerateShaderCode(body).c_str());
    278   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    279   EXPECT_THAT(getDiagnosticString(),
    280               HasSubstr("Expected Index to be int scalar"));
    281 }
    282 
    283 TEST_F(ValidateComposites, CompositeConstructNotComposite) {
    284   const std::string body = R"(
    285 %val1 = OpCompositeConstruct %f32 %f32_1
    286 )";
    287 
    288   CompileSuccessfully(GenerateShaderCode(body).c_str());
    289   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    290   EXPECT_THAT(getDiagnosticString(),
    291               HasSubstr("Expected Result Type to be a composite type"));
    292 }
    293 
    294 TEST_F(ValidateComposites, CompositeConstructVectorSuccess) {
    295   const std::string body = R"(
    296 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12
    297 %val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0
    298 %val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12
    299 %val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
    300 )";
    301 
    302   CompileSuccessfully(GenerateShaderCode(body).c_str());
    303   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    304 }
    305 
    306 TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) {
    307   const std::string body = R"(
    308 %val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123
    309 )";
    310 
    311   CompileSuccessfully(GenerateShaderCode(body).c_str());
    312   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    313   EXPECT_THAT(getDiagnosticString(),
    314               HasSubstr("Expected number of constituents to be at least 2"));
    315 }
    316 
    317 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) {
    318   const std::string body = R"(
    319 %val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12
    320 )";
    321 
    322   CompileSuccessfully(GenerateShaderCode(body).c_str());
    323   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
    324   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%float] cannot be a "
    325                                                "type"));
    326 }
    327 
    328 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) {
    329   const std::string body = R"(
    330 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01
    331 )";
    332 
    333   CompileSuccessfully(GenerateShaderCode(body).c_str());
    334   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    335   EXPECT_THAT(
    336       getDiagnosticString(),
    337       HasSubstr("Expected Constituents to be scalars or vectors of the same "
    338                 "type as Result Type components"));
    339 }
    340 
    341 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) {
    342   const std::string body = R"(
    343 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0
    344 )";
    345 
    346   CompileSuccessfully(GenerateShaderCode(body).c_str());
    347   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    348   EXPECT_THAT(
    349       getDiagnosticString(),
    350       HasSubstr("Expected Constituents to be scalars or vectors of the same "
    351                 "type as Result Type components"));
    352 }
    353 
    354 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) {
    355   const std::string body = R"(
    356 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0
    357 )";
    358 
    359   CompileSuccessfully(GenerateShaderCode(body).c_str());
    360   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    361   EXPECT_THAT(
    362       getDiagnosticString(),
    363       HasSubstr("Expected total number of given components to be equal to the "
    364                 "size of Result Type vector"));
    365 }
    366 
    367 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) {
    368   const std::string body = R"(
    369 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0
    370 )";
    371 
    372   CompileSuccessfully(GenerateShaderCode(body).c_str());
    373   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    374   EXPECT_THAT(
    375       getDiagnosticString(),
    376       HasSubstr("Expected total number of given components to be equal to the "
    377                 "size of Result Type vector"));
    378 }
    379 
    380 TEST_F(ValidateComposites, CompositeConstructMatrixSuccess) {
    381   const std::string body = R"(
    382 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12
    383 %val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
    384 )";
    385 
    386   CompileSuccessfully(GenerateShaderCode(body).c_str());
    387   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    388 }
    389 
    390 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) {
    391   const std::string body = R"(
    392 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12
    393 )";
    394 
    395   CompileSuccessfully(GenerateShaderCode(body).c_str());
    396   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    397   EXPECT_THAT(
    398       getDiagnosticString(),
    399       HasSubstr("Expected total number of Constituents to be equal to the "
    400                 "number of columns of Result Type matrix"));
    401 }
    402 
    403 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) {
    404   const std::string body = R"(
    405 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12
    406 )";
    407 
    408   CompileSuccessfully(GenerateShaderCode(body).c_str());
    409   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    410   EXPECT_THAT(
    411       getDiagnosticString(),
    412       HasSubstr("Expected total number of Constituents to be equal to the "
    413                 "number of columns of Result Type matrix"));
    414 }
    415 
    416 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) {
    417   const std::string body = R"(
    418 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01
    419 )";
    420 
    421   CompileSuccessfully(GenerateShaderCode(body).c_str());
    422   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    423   EXPECT_THAT(
    424       getDiagnosticString(),
    425       HasSubstr("Expected Constituent type to be equal to the column type "
    426                 "Result Type matrix"));
    427 }
    428 
    429 TEST_F(ValidateComposites, CompositeConstructArraySuccess) {
    430   const std::string body = R"(
    431 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
    432 )";
    433 
    434   CompileSuccessfully(GenerateShaderCode(body).c_str());
    435   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    436 }
    437 
    438 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) {
    439   const std::string body = R"(
    440 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12
    441 )";
    442 
    443   CompileSuccessfully(GenerateShaderCode(body).c_str());
    444   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    445   EXPECT_THAT(
    446       getDiagnosticString(),
    447       HasSubstr("Expected total number of Constituents to be equal to the "
    448                 "number of elements of Result Type array"));
    449 }
    450 
    451 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) {
    452   const std::string body = R"(
    453 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12
    454 )";
    455 
    456   CompileSuccessfully(GenerateShaderCode(body).c_str());
    457   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    458   EXPECT_THAT(
    459       getDiagnosticString(),
    460       HasSubstr("Expected total number of Constituents to be equal to the "
    461                 "number of elements of Result Type array"));
    462 }
    463 
    464 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) {
    465   const std::string body = R"(
    466 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12
    467 )";
    468 
    469   CompileSuccessfully(GenerateShaderCode(body).c_str());
    470   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    471   EXPECT_THAT(
    472       getDiagnosticString(),
    473       HasSubstr("Expected Constituent type to be equal to the column type "
    474                 "Result Type array"));
    475 }
    476 
    477 TEST_F(ValidateComposites, CompositeConstructStructSuccess) {
    478   const std::string body = R"(
    479 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1
    480 )";
    481 
    482   CompileSuccessfully(GenerateShaderCode(body).c_str());
    483   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    484 }
    485 
    486 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) {
    487   const std::string body = R"(
    488 %val1 = OpCompositeConstruct %f32u32struct %f32_0
    489 )";
    490 
    491   CompileSuccessfully(GenerateShaderCode(body).c_str());
    492   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    493   EXPECT_THAT(
    494       getDiagnosticString(),
    495       HasSubstr("Expected total number of Constituents to be equal to the "
    496                 "number of members of Result Type struct"));
    497 }
    498 
    499 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) {
    500   const std::string body = R"(
    501 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1
    502 )";
    503 
    504   CompileSuccessfully(GenerateShaderCode(body).c_str());
    505   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    506   EXPECT_THAT(
    507       getDiagnosticString(),
    508       HasSubstr("Expected total number of Constituents to be equal to the "
    509                 "number of members of Result Type struct"));
    510 }
    511 
    512 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) {
    513   const std::string body = R"(
    514 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1
    515 )";
    516 
    517   CompileSuccessfully(GenerateShaderCode(body).c_str());
    518   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    519   EXPECT_THAT(getDiagnosticString(),
    520               HasSubstr("Expected Constituent type to be equal to the "
    521                         "corresponding member type of Result Type struct"));
    522 }
    523 
    524 TEST_F(ValidateComposites, CopyObjectSuccess) {
    525   const std::string body = R"(
    526 %val1 = OpCopyObject %f32 %f32_0
    527 %val2 = OpCopyObject %f32vec4 %f32vec4_0123
    528 )";
    529 
    530   CompileSuccessfully(GenerateShaderCode(body).c_str());
    531   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    532 }
    533 
    534 TEST_F(ValidateComposites, CopyObjectResultTypeNotType) {
    535   const std::string body = R"(
    536 %val1 = OpCopyObject %f32_0 %f32_0
    537 )";
    538 
    539   CompileSuccessfully(GenerateShaderCode(body).c_str());
    540   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
    541   EXPECT_THAT(getDiagnosticString(),
    542               HasSubstr("ID 19[%float_0] is not a type id"));
    543 }
    544 
    545 TEST_F(ValidateComposites, CopyObjectWrongOperandType) {
    546   const std::string body = R"(
    547 %val1 = OpCopyObject %f32 %u32_0
    548 )";
    549 
    550   CompileSuccessfully(GenerateShaderCode(body).c_str());
    551   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    552   EXPECT_THAT(
    553       getDiagnosticString(),
    554       HasSubstr("Expected Result Type and Operand type to be the same"));
    555 }
    556 
    557 TEST_F(ValidateComposites, TransposeSuccess) {
    558   const std::string body = R"(
    559 %val1 = OpTranspose %f32mat32 %f32mat23_121212
    560 %val2 = OpTranspose %f32mat22 %f32mat22_1212
    561 )";
    562 
    563   CompileSuccessfully(GenerateShaderCode(body).c_str());
    564   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    565 }
    566 
    567 TEST_F(ValidateComposites, TransposeResultTypeNotMatrix) {
    568   const std::string body = R"(
    569 %val1 = OpTranspose %f32vec4 %f32mat22_1212
    570 )";
    571 
    572   CompileSuccessfully(GenerateShaderCode(body).c_str());
    573   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    574   EXPECT_THAT(getDiagnosticString(),
    575               HasSubstr("Expected Result Type to be a matrix type"));
    576 }
    577 
    578 TEST_F(ValidateComposites, TransposeDifferentComponentTypes) {
    579   const std::string body = R"(
    580 %val1 = OpTranspose %f64mat22 %f32mat22_1212
    581 )";
    582 
    583   CompileSuccessfully(GenerateShaderCode(body).c_str());
    584   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    585   EXPECT_THAT(
    586       getDiagnosticString(),
    587       HasSubstr("Expected component types of Matrix and Result Type to be "
    588                 "identical"));
    589 }
    590 
    591 TEST_F(ValidateComposites, TransposeIncompatibleDimensions1) {
    592   const std::string body = R"(
    593 %val1 = OpTranspose %f32mat23 %f32mat22_1212
    594 )";
    595 
    596   CompileSuccessfully(GenerateShaderCode(body).c_str());
    597   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    598   EXPECT_THAT(getDiagnosticString(),
    599               HasSubstr("Expected number of columns and the column size "
    600                         "of Matrix to be the reverse of those of Result Type"));
    601 }
    602 
    603 TEST_F(ValidateComposites, TransposeIncompatibleDimensions2) {
    604   const std::string body = R"(
    605 %val1 = OpTranspose %f32mat32 %f32mat22_1212
    606 )";
    607 
    608   CompileSuccessfully(GenerateShaderCode(body).c_str());
    609   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    610   EXPECT_THAT(getDiagnosticString(),
    611               HasSubstr("Expected number of columns and the column size "
    612                         "of Matrix to be the reverse of those of Result Type"));
    613 }
    614 
    615 TEST_F(ValidateComposites, TransposeIncompatibleDimensions3) {
    616   const std::string body = R"(
    617 %val1 = OpTranspose %f32mat23 %f32mat23_121212
    618 )";
    619 
    620   CompileSuccessfully(GenerateShaderCode(body).c_str());
    621   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    622   EXPECT_THAT(getDiagnosticString(),
    623               HasSubstr("Expected number of columns and the column size "
    624                         "of Matrix to be the reverse of those of Result Type"));
    625 }
    626 
    627 TEST_F(ValidateComposites, CompositeExtractSuccess) {
    628   const std::string body = R"(
    629 %val1 = OpCompositeExtract %f32 %f32vec4_0123 1
    630 %val2 = OpCompositeExtract %u32 %u32vec4_0123 0
    631 %val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1
    632 %val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0
    633 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
    634 %val5 = OpCompositeExtract %f32vec2 %array 2
    635 %val6 = OpCompositeExtract %f32 %array 2 1
    636 %struct = OpLoad %big_struct %var_big_struct
    637 %val7 = OpCompositeExtract %f32 %struct 0
    638 %val8 = OpCompositeExtract %f32vec4 %struct 1
    639 %val9 = OpCompositeExtract %f32 %struct 1 2
    640 %val10 = OpCompositeExtract %f32mat23 %struct 2
    641 %val11 = OpCompositeExtract %f32vec2 %struct 2 2
    642 %val12 = OpCompositeExtract %f32 %struct 2 2 1
    643 %val13 = OpCompositeExtract %f32vec2 %struct 3 2
    644 %val14 = OpCompositeExtract %f32 %struct 3 2 1
    645 %val15 = OpCompositeExtract %f32vec2 %struct 4 100
    646 %val16 = OpCompositeExtract %f32 %struct 4 1000 1
    647 %val17 = OpCompositeExtract %f32 %struct 5 0
    648 %val18 = OpCompositeExtract %u32 %struct 5 1
    649 %val19 = OpCompositeExtract %big_struct %struct
    650 )";
    651 
    652   CompileSuccessfully(GenerateShaderCode(body));
    653   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    654 }
    655 
    656 TEST_F(ValidateComposites, CompositeExtractNotObject) {
    657   const std::string body = R"(
    658 %val1 = OpCompositeExtract %f32 %f32vec4 1
    659 )";
    660 
    661   CompileSuccessfully(GenerateShaderCode(body));
    662   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
    663   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 11[%v4float] cannot "
    664                                                "be a type"));
    665 }
    666 
    667 TEST_F(ValidateComposites, CompositeExtractNotComposite) {
    668   const std::string body = R"(
    669 %val1 = OpCompositeExtract %f32 %f32_1 0
    670 )";
    671 
    672   CompileSuccessfully(GenerateShaderCode(body));
    673   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    674   EXPECT_THAT(getDiagnosticString(),
    675               HasSubstr("Reached non-composite type while indexes still remain "
    676                         "to be traversed."));
    677 }
    678 
    679 TEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) {
    680   const std::string body = R"(
    681 %val1 = OpCompositeExtract %f32 %f32vec4_0123 4
    682 )";
    683 
    684   CompileSuccessfully(GenerateShaderCode(body));
    685   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    686   EXPECT_THAT(getDiagnosticString(),
    687               HasSubstr("Vector access is out of bounds, "
    688                         "vector size is 4, but access index is 4"));
    689 }
    690 
    691 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) {
    692   const std::string body = R"(
    693 %val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1
    694 )";
    695 
    696   CompileSuccessfully(GenerateShaderCode(body));
    697   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    698   EXPECT_THAT(getDiagnosticString(),
    699               HasSubstr("Matrix access is out of bounds, "
    700                         "matrix has 3 columns, but access index is 3"));
    701 }
    702 
    703 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) {
    704   const std::string body = R"(
    705 %val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5
    706 )";
    707 
    708   CompileSuccessfully(GenerateShaderCode(body));
    709   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    710   EXPECT_THAT(getDiagnosticString(),
    711               HasSubstr("Vector access is out of bounds, "
    712                         "vector size is 2, but access index is 5"));
    713 }
    714 
    715 TEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) {
    716   const std::string body = R"(
    717 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
    718 %val1 = OpCompositeExtract %f32vec2 %array 3
    719 )";
    720 
    721   CompileSuccessfully(GenerateShaderCode(body));
    722   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    723   EXPECT_THAT(getDiagnosticString(),
    724               HasSubstr("Array access is out of bounds, "
    725                         "array size is 3, but access index is 3"));
    726 }
    727 
    728 TEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) {
    729   const std::string body = R"(
    730 %struct = OpLoad %big_struct %var_big_struct
    731 %val1 = OpCompositeExtract %f32 %struct 6
    732 )";
    733 
    734   CompileSuccessfully(GenerateShaderCode(body));
    735   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    736   EXPECT_THAT(getDiagnosticString(),
    737               HasSubstr("Index is out of bounds, can not find index 6 in the "
    738                         "structure <id> '37'. This structure has 6 members. "
    739                         "Largest valid index is 5."));
    740 }
    741 
    742 TEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) {
    743   const std::string body = R"(
    744 %struct = OpLoad %big_struct %var_big_struct
    745 %val1 = OpCompositeExtract %f32 %struct 3 1 5
    746 )";
    747 
    748   CompileSuccessfully(GenerateShaderCode(body));
    749   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    750   EXPECT_THAT(getDiagnosticString(),
    751               HasSubstr("Vector access is out of bounds, "
    752                         "vector size is 2, but access index is 5"));
    753 }
    754 
    755 TEST_F(ValidateComposites, CompositeExtractTooManyIndices) {
    756   const std::string body = R"(
    757 %struct = OpLoad %big_struct %var_big_struct
    758 %val1 = OpCompositeExtract %f32 %struct 3 1 1 2
    759 )";
    760 
    761   CompileSuccessfully(GenerateShaderCode(body));
    762   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    763   EXPECT_THAT(getDiagnosticString(),
    764               HasSubstr("Reached non-composite type while "
    765                         "indexes still remain to be traversed."));
    766 }
    767 
    768 TEST_F(ValidateComposites, CompositeExtractWrongType1) {
    769   const std::string body = R"(
    770 %struct = OpLoad %big_struct %var_big_struct
    771 %val1 = OpCompositeExtract %f32vec2 %struct 3 1 1
    772 )";
    773 
    774   CompileSuccessfully(GenerateShaderCode(body));
    775   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    776   EXPECT_THAT(
    777       getDiagnosticString(),
    778       HasSubstr(
    779           "Result type (OpTypeVector) does not match the type that results "
    780           "from indexing into the composite (OpTypeFloat)."));
    781 }
    782 
    783 TEST_F(ValidateComposites, CompositeExtractWrongType2) {
    784   const std::string body = R"(
    785 %struct = OpLoad %big_struct %var_big_struct
    786 %val1 = OpCompositeExtract %f32 %struct 3 1
    787 )";
    788 
    789   CompileSuccessfully(GenerateShaderCode(body));
    790   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    791   EXPECT_THAT(getDiagnosticString(),
    792               HasSubstr("Result type (OpTypeFloat) does not match the type "
    793                         "that results from indexing into the composite "
    794                         "(OpTypeVector)."));
    795 }
    796 
    797 TEST_F(ValidateComposites, CompositeExtractWrongType3) {
    798   const std::string body = R"(
    799 %struct = OpLoad %big_struct %var_big_struct
    800 %val1 = OpCompositeExtract %f32 %struct 2 1
    801 )";
    802 
    803   CompileSuccessfully(GenerateShaderCode(body));
    804   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    805   EXPECT_THAT(getDiagnosticString(),
    806               HasSubstr("Result type (OpTypeFloat) does not match the type "
    807                         "that results from indexing into the composite "
    808                         "(OpTypeVector)."));
    809 }
    810 
    811 TEST_F(ValidateComposites, CompositeExtractWrongType4) {
    812   const std::string body = R"(
    813 %struct = OpLoad %big_struct %var_big_struct
    814 %val1 = OpCompositeExtract %f32 %struct 4 1
    815 )";
    816 
    817   CompileSuccessfully(GenerateShaderCode(body));
    818   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    819   EXPECT_THAT(getDiagnosticString(),
    820               HasSubstr("Result type (OpTypeFloat) does not match the type "
    821                         "that results from indexing into the composite "
    822                         "(OpTypeVector)."));
    823 }
    824 
    825 TEST_F(ValidateComposites, CompositeExtractWrongType5) {
    826   const std::string body = R"(
    827 %struct = OpLoad %big_struct %var_big_struct
    828 %val1 = OpCompositeExtract %f32 %struct 5 1
    829 )";
    830 
    831   CompileSuccessfully(GenerateShaderCode(body));
    832   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    833   EXPECT_THAT(
    834       getDiagnosticString(),
    835       HasSubstr(
    836           "Result type (OpTypeFloat) does not match the "
    837           "type that results from indexing into the composite (OpTypeInt)."));
    838 }
    839 
    840 TEST_F(ValidateComposites, CompositeInsertSuccess) {
    841   const std::string body = R"(
    842 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0
    843 %val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0
    844 %val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1
    845 %val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0
    846 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
    847 %val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2
    848 %val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1
    849 %struct = OpLoad %big_struct %var_big_struct
    850 %val7 = OpCompositeInsert %big_struct %f32_3 %struct 0
    851 %val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1
    852 %val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2
    853 %val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2
    854 %val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2
    855 %val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1
    856 %val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2
    857 %val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1
    858 %val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 100
    859 %val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 1000 1
    860 %val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0
    861 %val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1
    862 %val19 = OpCompositeInsert %big_struct %struct %struct
    863 )";
    864 
    865   CompileSuccessfully(GenerateShaderCode(body));
    866   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    867 }
    868 
    869 TEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) {
    870   const std::string body = R"(
    871 %val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0
    872 )";
    873 
    874   CompileSuccessfully(GenerateShaderCode(body));
    875   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    876   EXPECT_THAT(getDiagnosticString(),
    877               HasSubstr("The Result Type must be the same as Composite type in "
    878                         "OpCompositeInsert yielding Result Id 5."));
    879 }
    880 
    881 TEST_F(ValidateComposites, CompositeInsertNotComposite) {
    882   const std::string body = R"(
    883 %val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0
    884 )";
    885 
    886   CompileSuccessfully(GenerateShaderCode(body));
    887   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    888   EXPECT_THAT(getDiagnosticString(),
    889               HasSubstr("Reached non-composite type while indexes still remain "
    890                         "to be traversed."));
    891 }
    892 
    893 TEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) {
    894   const std::string body = R"(
    895 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4
    896 )";
    897 
    898   CompileSuccessfully(GenerateShaderCode(body));
    899   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    900   EXPECT_THAT(getDiagnosticString(),
    901               HasSubstr("Vector access is out of bounds, "
    902                         "vector size is 4, but access index is 4"));
    903 }
    904 
    905 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) {
    906   const std::string body = R"(
    907 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1
    908 )";
    909 
    910   CompileSuccessfully(GenerateShaderCode(body));
    911   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    912   EXPECT_THAT(getDiagnosticString(),
    913               HasSubstr("Matrix access is out of bounds, "
    914                         "matrix has 3 columns, but access index is 3"));
    915 }
    916 
    917 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) {
    918   const std::string body = R"(
    919 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5
    920 )";
    921 
    922   CompileSuccessfully(GenerateShaderCode(body));
    923   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    924   EXPECT_THAT(getDiagnosticString(),
    925               HasSubstr("Vector access is out of bounds, "
    926                         "vector size is 2, but access index is 5"));
    927 }
    928 
    929 TEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) {
    930   const std::string body = R"(
    931 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
    932 %val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3
    933 )";
    934 
    935   CompileSuccessfully(GenerateShaderCode(body));
    936   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    937   EXPECT_THAT(getDiagnosticString(),
    938               HasSubstr("Array access is out of bounds, array "
    939                         "size is 3, but access index is 3"));
    940 }
    941 
    942 TEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) {
    943   const std::string body = R"(
    944 %struct = OpLoad %big_struct %var_big_struct
    945 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 6
    946 )";
    947 
    948   CompileSuccessfully(GenerateShaderCode(body));
    949   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    950   EXPECT_THAT(getDiagnosticString(),
    951               HasSubstr("Index is out of bounds, can not find index 6 in the "
    952                         "structure <id> '37'. This structure has 6 members. "
    953                         "Largest valid index is 5."));
    954 }
    955 
    956 TEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) {
    957   const std::string body = R"(
    958 %struct = OpLoad %big_struct %var_big_struct
    959 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5
    960 )";
    961 
    962   CompileSuccessfully(GenerateShaderCode(body));
    963   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    964   EXPECT_THAT(getDiagnosticString(),
    965               HasSubstr("Vector access is out of bounds, "
    966                         "vector size is 2, but access index is 5"));
    967 }
    968 
    969 TEST_F(ValidateComposites, CompositeInsertTooManyIndices) {
    970   const std::string body = R"(
    971 %struct = OpLoad %big_struct %var_big_struct
    972 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2
    973 )";
    974 
    975   CompileSuccessfully(GenerateShaderCode(body));
    976   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    977   EXPECT_THAT(getDiagnosticString(),
    978               HasSubstr("Reached non-composite type while indexes still remain "
    979                         "to be traversed."));
    980 }
    981 
    982 TEST_F(ValidateComposites, CompositeInsertWrongType1) {
    983   const std::string body = R"(
    984 %struct = OpLoad %big_struct %var_big_struct
    985 %val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1
    986 )";
    987 
    988   CompileSuccessfully(GenerateShaderCode(body));
    989   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    990   EXPECT_THAT(getDiagnosticString(),
    991               HasSubstr("The Object type (OpTypeVector) does not match the "
    992                         "type that results from indexing into the Composite "
    993                         "(OpTypeFloat)."));
    994 }
    995 
    996 TEST_F(ValidateComposites, CompositeInsertWrongType2) {
    997   const std::string body = R"(
    998 %struct = OpLoad %big_struct %var_big_struct
    999 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1
   1000 )";
   1001 
   1002   CompileSuccessfully(GenerateShaderCode(body));
   1003   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1004   EXPECT_THAT(getDiagnosticString(),
   1005               HasSubstr("The Object type (OpTypeFloat) does not match the type "
   1006                         "that results from indexing into the Composite "
   1007                         "(OpTypeVector)."));
   1008 }
   1009 
   1010 TEST_F(ValidateComposites, CompositeInsertWrongType3) {
   1011   const std::string body = R"(
   1012 %struct = OpLoad %big_struct %var_big_struct
   1013 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1
   1014 )";
   1015 
   1016   CompileSuccessfully(GenerateShaderCode(body));
   1017   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1018   EXPECT_THAT(getDiagnosticString(),
   1019               HasSubstr("The Object type (OpTypeFloat) does not match the type "
   1020                         "that results from indexing into the Composite "
   1021                         "(OpTypeVector)."));
   1022 }
   1023 
   1024 TEST_F(ValidateComposites, CompositeInsertWrongType4) {
   1025   const std::string body = R"(
   1026 %struct = OpLoad %big_struct %var_big_struct
   1027 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1
   1028 )";
   1029 
   1030   CompileSuccessfully(GenerateShaderCode(body));
   1031   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1032   EXPECT_THAT(getDiagnosticString(),
   1033               HasSubstr("The Object type (OpTypeFloat) does not match the type "
   1034                         "that results from indexing into the Composite "
   1035                         "(OpTypeVector)."));
   1036 }
   1037 
   1038 TEST_F(ValidateComposites, CompositeInsertWrongType5) {
   1039   const std::string body = R"(
   1040 %struct = OpLoad %big_struct %var_big_struct
   1041 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1
   1042 )";
   1043 
   1044   CompileSuccessfully(GenerateShaderCode(body));
   1045   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1046   EXPECT_THAT(getDiagnosticString(),
   1047               HasSubstr("The Object type (OpTypeFloat) does not match the type "
   1048                         "that results from indexing into the Composite "
   1049                         "(OpTypeInt)."));
   1050 }
   1051 
   1052 // Tests ported from val_id_test.cpp.
   1053 
   1054 // Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes.
   1055 TEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) {
   1056   int depth = 255;
   1057   std::string header = GetHeaderForTestsFromValId();
   1058   header.erase(header.find("%func"));
   1059   std::ostringstream spirv;
   1060   spirv << header << std::endl;
   1061 
   1062   // Build nested structures. Struct 'i' contains struct 'i-1'
   1063   spirv << "%s_depth_1 = OpTypeStruct %float\n";
   1064   for (int i = 2; i <= depth; ++i) {
   1065     spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
   1066   }
   1067 
   1068   // Define Pointer and Variable to use for CompositeExtract/Insert.
   1069   spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
   1070         << depth << "\n";
   1071   spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
   1072 
   1073   // Function Start
   1074   spirv << R"(
   1075   %func = OpFunction %void None %void_f
   1076   %my_label = OpLabel
   1077   )";
   1078 
   1079   // OpCompositeExtract/Insert with 'n' indexes (n = depth)
   1080   spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl;
   1081   spirv << "%entry = OpCompositeExtract  %float %deep";
   1082   for (int i = 0; i < depth; ++i) {
   1083     spirv << " 0";
   1084   }
   1085   spirv << std::endl;
   1086   spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth
   1087         << " %entry %deep";
   1088   for (int i = 0; i < depth; ++i) {
   1089     spirv << " 0";
   1090   }
   1091   spirv << std::endl;
   1092 
   1093   // Function end
   1094   spirv << R"(
   1095     OpReturn
   1096     OpFunctionEnd
   1097   )";
   1098   CompileSuccessfully(spirv.str());
   1099   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1100 }
   1101 
   1102 // Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255.
   1103 TEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) {
   1104   std::ostringstream spirv;
   1105   spirv << GetHeaderForTestsFromValId() << std::endl;
   1106   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
   1107   spirv << "%entry = OpCompositeExtract %float %matrix";
   1108   for (int i = 0; i < 256; ++i) {
   1109     spirv << " 0";
   1110   }
   1111   spirv << R"(
   1112     OpReturn
   1113     OpFunctionEnd
   1114   )";
   1115   CompileSuccessfully(spirv.str());
   1116   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1117   EXPECT_THAT(getDiagnosticString(),
   1118               HasSubstr("The number of indexes in OpCompositeExtract may not "
   1119                         "exceed 255. Found 256 indexes."));
   1120 }
   1121 
   1122 // Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255.
   1123 TEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) {
   1124   std::ostringstream spirv;
   1125   spirv << GetHeaderForTestsFromValId() << std::endl;
   1126   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
   1127   spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
   1128   for (int i = 0; i < 256; ++i) {
   1129     spirv << " 0";
   1130   }
   1131   spirv << R"(
   1132     OpReturn
   1133     OpFunctionEnd
   1134   )";
   1135   CompileSuccessfully(spirv.str());
   1136   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1137   EXPECT_THAT(getDiagnosticString(),
   1138               HasSubstr("The number of indexes in OpCompositeInsert may not "
   1139                         "exceed 255. Found 256 indexes."));
   1140 }
   1141 
   1142 // Invalid: In OpCompositeInsert, result type must be the same as composite type
   1143 TEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) {
   1144   std::ostringstream spirv;
   1145   spirv << GetHeaderForTestsFromValId() << std::endl;
   1146   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
   1147   spirv << "%float_entry = OpCompositeExtract  %float %matrix 0 1" << std::endl;
   1148   spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1"
   1149         << std::endl;
   1150   spirv << R"(OpReturn
   1151               OpFunctionEnd)";
   1152   CompileSuccessfully(spirv.str());
   1153   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1154   EXPECT_THAT(getDiagnosticString(),
   1155               HasSubstr("The Result Type must be the same as Composite type"));
   1156 }
   1157 
   1158 // Valid: No Indexes were passed to OpCompositeExtract, and the Result Type is
   1159 // the same as the Base Composite type.
   1160 TEST_F(ValidateComposites, CompositeExtractNoIndexesGood) {
   1161   std::ostringstream spirv;
   1162   spirv << GetHeaderForTestsFromValId() << std::endl;
   1163   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
   1164   spirv << "%float_entry = OpCompositeExtract  %mat4x3 %matrix" << std::endl;
   1165   spirv << R"(OpReturn
   1166               OpFunctionEnd)";
   1167   CompileSuccessfully(spirv.str());
   1168   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1169 }
   1170 
   1171 // Invalid: No Indexes were passed to OpCompositeExtract, but the Result Type is
   1172 // different from the Base Composite type.
   1173 TEST_F(ValidateComposites, CompositeExtractNoIndexesBad) {
   1174   std::ostringstream spirv;
   1175   spirv << GetHeaderForTestsFromValId() << std::endl;
   1176   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
   1177   spirv << "%float_entry = OpCompositeExtract  %float %matrix" << std::endl;
   1178   spirv << R"(OpReturn
   1179               OpFunctionEnd)";
   1180   CompileSuccessfully(spirv.str());
   1181   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1182   EXPECT_THAT(getDiagnosticString(),
   1183               HasSubstr("Result type (OpTypeFloat) does not match the type "
   1184                         "that results from indexing into the composite "
   1185                         "(OpTypeMatrix)."));
   1186 }
   1187 
   1188 // Valid: No Indexes were passed to OpCompositeInsert, and the type of the
   1189 // Object<id> argument matches the Composite type.
   1190 TEST_F(ValidateComposites, CompositeInsertMissingIndexesGood) {
   1191   std::ostringstream spirv;
   1192   spirv << GetHeaderForTestsFromValId() << std::endl;
   1193   spirv << "%matrix   = OpLoad %mat4x3 %my_matrix" << std::endl;
   1194   spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl;
   1195   spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix";
   1196   spirv << R"(
   1197               OpReturn
   1198               OpFunctionEnd)";
   1199   CompileSuccessfully(spirv.str());
   1200   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1201 }
   1202 
   1203 // Invalid: No Indexes were passed to OpCompositeInsert, but the type of the
   1204 // Object<id> argument does not match the Composite type.
   1205 TEST_F(ValidateComposites, CompositeInsertMissingIndexesBad) {
   1206   std::ostringstream spirv;
   1207   spirv << GetHeaderForTestsFromValId() << std::endl;
   1208   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
   1209   spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
   1210   spirv << R"(
   1211               OpReturn
   1212               OpFunctionEnd)";
   1213   CompileSuccessfully(spirv.str());
   1214   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1215   EXPECT_THAT(getDiagnosticString(),
   1216               HasSubstr("The Object type (OpTypeInt) does not match the type "
   1217                         "that results from indexing into the Composite "
   1218                         "(OpTypeMatrix)."));
   1219 }
   1220 
   1221 // Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
   1222 TEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) {
   1223   // indexes that we are passing are: 0, 3, 1, 2, 0
   1224   // 0 will select the struct_s within the base struct (blockName)
   1225   // 3 will select the Array that contains 5 matrices
   1226   // 1 will select the Matrix that is at index 1 of the array
   1227   // 2 will select the column (which is a vector) within the matrix at index 2
   1228   // 0 will select the element at the index 0 of the vector. (which is a float).
   1229   std::ostringstream spirv;
   1230   spirv << GetHeaderForTestsFromValId() << R"(
   1231     %myblock = OpLoad %struct_blockName %blockName_var
   1232     %ss = OpCompositeExtract %struct_s %myblock 0
   1233     %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3
   1234     %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1
   1235     %sc = OpCompositeExtract %v3float %myblock 0 3 1 2
   1236     %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
   1237     ;
   1238     ; Now let's insert back at different levels...
   1239     ;
   1240     %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0
   1241     %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3
   1242     %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1
   1243     %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2
   1244     %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0
   1245     OpReturn
   1246     OpFunctionEnd
   1247   )";
   1248 
   1249   CompileSuccessfully(spirv.str());
   1250   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1251 }
   1252 
   1253 // Invalid. More indexes are provided than needed for OpCompositeExtract.
   1254 TEST_F(ValidateComposites, CompositeExtractReachedScalarBad) {
   1255   // indexes that we are passing are: 0, 3, 1, 2, 0
   1256   // 0 will select the struct_s within the base struct (blockName)
   1257   // 3 will select the Array that contains 5 matrices
   1258   // 1 will select the Matrix that is at index 1 of the array
   1259   // 2 will select the column (which is a vector) within the matrix at index 2
   1260   // 0 will select the element at the index 0 of the vector. (which is a float).
   1261   std::ostringstream spirv;
   1262   spirv << GetHeaderForTestsFromValId() << R"(
   1263     %myblock = OpLoad %struct_blockName %blockName_var
   1264     %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1
   1265     OpReturn
   1266     OpFunctionEnd
   1267   )";
   1268 
   1269   CompileSuccessfully(spirv.str());
   1270   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1271   EXPECT_THAT(getDiagnosticString(),
   1272               HasSubstr("Reached non-composite type while indexes still remain "
   1273                         "to be traversed."));
   1274 }
   1275 
   1276 // Invalid. More indexes are provided than needed for OpCompositeInsert.
   1277 TEST_F(ValidateComposites, CompositeInsertReachedScalarBad) {
   1278   // indexes that we are passing are: 0, 3, 1, 2, 0
   1279   // 0 will select the struct_s within the base struct (blockName)
   1280   // 3 will select the Array that contains 5 matrices
   1281   // 1 will select the Matrix that is at index 1 of the array
   1282   // 2 will select the column (which is a vector) within the matrix at index 2
   1283   // 0 will select the element at the index 0 of the vector. (which is a float).
   1284   std::ostringstream spirv;
   1285   spirv << GetHeaderForTestsFromValId() << R"(
   1286     %myblock = OpLoad %struct_blockName %blockName_var
   1287     %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
   1288     %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1
   1289     OpReturn
   1290     OpFunctionEnd
   1291   )";
   1292 
   1293   CompileSuccessfully(spirv.str());
   1294   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1295   EXPECT_THAT(getDiagnosticString(),
   1296               HasSubstr("Reached non-composite type while indexes still remain "
   1297                         "to be traversed."));
   1298 }
   1299 
   1300 // Invalid. Result type doesn't match the type we get from indexing into
   1301 // the composite.
   1302 TEST_F(ValidateComposites,
   1303        CompositeExtractResultTypeDoesntMatchIndexedTypeBad) {
   1304   // indexes that we are passing are: 0, 3, 1, 2, 0
   1305   // 0 will select the struct_s within the base struct (blockName)
   1306   // 3 will select the Array that contains 5 matrices
   1307   // 1 will select the Matrix that is at index 1 of the array
   1308   // 2 will select the column (which is a vector) within the matrix at index 2
   1309   // 0 will select the element at the index 0 of the vector. (which is a float).
   1310   std::ostringstream spirv;
   1311   spirv << GetHeaderForTestsFromValId() << R"(
   1312     %myblock = OpLoad %struct_blockName %blockName_var
   1313     %fl = OpCompositeExtract %int %myblock 0 3 1 2 0
   1314     OpReturn
   1315     OpFunctionEnd
   1316   )";
   1317 
   1318   CompileSuccessfully(spirv.str());
   1319   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1320   EXPECT_THAT(getDiagnosticString(),
   1321               HasSubstr("Result type (OpTypeInt) does not match the type that "
   1322                         "results from indexing into the composite "
   1323                         "(OpTypeFloat)."));
   1324 }
   1325 
   1326 // Invalid. Given object type doesn't match the type we get from indexing into
   1327 // the composite.
   1328 TEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) {
   1329   // indexes that we are passing are: 0, 3, 1, 2, 0
   1330   // 0 will select the struct_s within the base struct (blockName)
   1331   // 3 will select the Array that contains 5 matrices
   1332   // 1 will select the Matrix that is at index 1 of the array
   1333   // 2 will select the column (which is a vector) within the matrix at index 2
   1334   // 0 will select the element at the index 0 of the vector. (which is a float).
   1335   // We are trying to insert an integer where we should be inserting a float.
   1336   std::ostringstream spirv;
   1337   spirv << GetHeaderForTestsFromValId() << R"(
   1338     %myblock = OpLoad %struct_blockName %blockName_var
   1339     %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0
   1340     OpReturn
   1341     OpFunctionEnd
   1342   )";
   1343 
   1344   CompileSuccessfully(spirv.str());
   1345   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1346   EXPECT_THAT(getDiagnosticString(),
   1347               HasSubstr("The Object type (OpTypeInt) does not match the type "
   1348                         "that results from indexing into the Composite "
   1349                         "(OpTypeFloat)."));
   1350 }
   1351 
   1352 // Invalid. Index into a struct is larger than the number of struct members.
   1353 TEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) {
   1354   // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
   1355   std::ostringstream spirv;
   1356   spirv << GetHeaderForTestsFromValId() << R"(
   1357     %myblock = OpLoad %struct_blockName %blockName_var
   1358     %ss = OpCompositeExtract %struct_s %myblock 3
   1359     OpReturn
   1360     OpFunctionEnd
   1361   )";
   1362 
   1363   CompileSuccessfully(spirv.str());
   1364   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1365   EXPECT_THAT(getDiagnosticString(),
   1366               HasSubstr("Index is out of bounds, can not find index 3 in the "
   1367                         "structure <id> '25'. This structure has 3 members. "
   1368                         "Largest valid index is 2."));
   1369 }
   1370 
   1371 // Invalid. Index into a struct is larger than the number of struct members.
   1372 TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) {
   1373   // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
   1374   std::ostringstream spirv;
   1375   spirv << GetHeaderForTestsFromValId() << R"(
   1376     %myblock = OpLoad %struct_blockName %blockName_var
   1377     %ss = OpCompositeExtract %struct_s %myblock 0
   1378     %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3
   1379     OpReturn
   1380     OpFunctionEnd
   1381   )";
   1382 
   1383   CompileSuccessfully(spirv.str());
   1384   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1385   EXPECT_THAT(
   1386       getDiagnosticString(),
   1387       HasSubstr("Index is out of bounds, can not find index 3 in the structure "
   1388                 "<id> '25'. This structure has 3 members. Largest valid index "
   1389                 "is 2."));
   1390 }
   1391 
   1392 // #1403: Ensure that the default spec constant value is not used to check the
   1393 // extract index.
   1394 TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) {
   1395   std::string spirv = R"(
   1396 OpCapability Kernel
   1397 OpCapability Linkage
   1398 OpMemoryModel Logical OpenCL
   1399 OpDecorate %spec_const SpecId 1
   1400 %void = OpTypeVoid
   1401 %uint = OpTypeInt 32 0
   1402 %spec_const = OpSpecConstant %uint 3
   1403 %uint_array = OpTypeArray %uint %spec_const
   1404 %undef = OpUndef %uint_array
   1405 %voidf = OpTypeFunction %void
   1406 %func = OpFunction %void None %voidf
   1407 %1 = OpLabel
   1408 %2 = OpCompositeExtract %uint %undef 4
   1409 OpReturn
   1410 OpFunctionEnd
   1411 )";
   1412 
   1413   CompileSuccessfully(spirv);
   1414   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1415 }
   1416 
   1417 // #1403: Ensure that spec constant ops do not produce false positives.
   1418 TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) {
   1419   std::string spirv = R"(
   1420 OpCapability Kernel
   1421 OpCapability Linkage
   1422 OpMemoryModel Logical OpenCL
   1423 OpDecorate %spec_const SpecId 1
   1424 %void = OpTypeVoid
   1425 %uint = OpTypeInt 32 0
   1426 %const = OpConstant %uint 1
   1427 %spec_const = OpSpecConstant %uint 3
   1428 %spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const
   1429 %uint_array = OpTypeArray %uint %spec_const_op
   1430 %undef = OpUndef %uint_array
   1431 %voidf = OpTypeFunction %void
   1432 %func = OpFunction %void None %voidf
   1433 %1 = OpLabel
   1434 %2 = OpCompositeExtract %uint %undef 4
   1435 OpReturn
   1436 OpFunctionEnd
   1437 )";
   1438 
   1439   CompileSuccessfully(spirv);
   1440   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1441 }
   1442 
   1443 // #1403: Ensure that the default spec constant value is not used to check the
   1444 // size of the array for a composite construct. This code has limited actual
   1445 // value as it is incorrect unless the specialization constant is assigned the
   1446 // value of 2, but it is still a valid module.
   1447 TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) {
   1448   std::string spirv = R"(
   1449 OpCapability Kernel
   1450 OpCapability Linkage
   1451 OpMemoryModel Logical OpenCL
   1452 OpDecorate %spec_const SpecId 1
   1453 %void = OpTypeVoid
   1454 %uint = OpTypeInt 32 0
   1455 %uint_0 = OpConstant %uint 0
   1456 %spec_const = OpSpecConstant %uint 3
   1457 %uint_array = OpTypeArray %uint %spec_const
   1458 %voidf = OpTypeFunction %void
   1459 %func = OpFunction %void None %voidf
   1460 %1 = OpLabel
   1461 %2 = OpCompositeConstruct %uint_array %uint_0 %uint_0
   1462 OpReturn
   1463 OpFunctionEnd
   1464 )";
   1465 
   1466   CompileSuccessfully(spirv);
   1467   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
   1468 }
   1469 
   1470 TEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
   1471   const std::string spirv = R"(
   1472 OpCapability Shader
   1473 OpCapability Linkage
   1474 OpMemoryModel Logical GLSL450
   1475 %void = OpTypeVoid
   1476 %float = OpTypeFloat 32
   1477 %v4float = OpTypeVector %float 4
   1478 %void_fn = OpTypeFunction %void
   1479 %float_0 = OpConstant %float 0
   1480 %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
   1481 %func = OpFunction %void None %void_fn
   1482 %1 = OpLabel
   1483 %ex = OpVectorExtractDynamic %float %v4float_0 %1
   1484 OpReturn
   1485 OpFunctionEnd
   1486 )";
   1487 
   1488   CompileSuccessfully(spirv);
   1489   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   1490   EXPECT_THAT(getDiagnosticString(),
   1491               HasSubstr("Expected Index to be int scalar"));
   1492 }
   1493 
   1494 }  // namespace
   1495 }  // namespace val
   1496 }  // namespace spvtools
   1497