| // Copyright (c) 2015-2016 The Khronos Group Inc. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | // Validation tests for OpVariable storage class | 
 |  | 
 | #include <sstream> | 
 | #include <string> | 
 | #include <tuple> | 
 |  | 
 | #include "gmock/gmock.h" | 
 | #include "val_fixtures.h" | 
 |  | 
 | using ::testing::HasSubstr; | 
 |  | 
 | using ValidateStorage = spvtest::ValidateBase<std::string>; | 
 |  | 
 | namespace { | 
 |  | 
 | TEST_F(ValidateStorage, FunctionStorageInsideFunction) { | 
 |   char str[] = R"( | 
 |           OpCapability Shader | 
 |           OpCapability Linkage | 
 |           OpMemoryModel Logical GLSL450 | 
 | %intt   = OpTypeInt 32 1 | 
 | %voidt  = OpTypeVoid | 
 | %vfunct = OpTypeFunction %voidt | 
 | %ptrt   = OpTypePointer Function %intt | 
 | %func   = OpFunction %voidt None %vfunct | 
 | %funcl  = OpLabel | 
 | %var    = OpVariable %ptrt Function | 
 |           OpReturn | 
 |           OpFunctionEnd | 
 | )"; | 
 |  | 
 |   CompileSuccessfully(str); | 
 |   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); | 
 | } | 
 |  | 
 | TEST_F(ValidateStorage, FunctionStorageOutsideFunction) { | 
 |   char str[] = R"( | 
 |           OpCapability Shader | 
 |           OpCapability Linkage | 
 |           OpMemoryModel Logical GLSL450 | 
 | %intt   = OpTypeInt 32 1 | 
 | %voidt  = OpTypeVoid | 
 | %vfunct = OpTypeFunction %voidt | 
 | %ptrt   = OpTypePointer Function %intt | 
 | %var    = OpVariable %ptrt Function | 
 | %func   = OpFunction %voidt None %vfunct | 
 | %funcl  = OpLabel | 
 |           OpReturn | 
 |           OpFunctionEnd | 
 | )"; | 
 |  | 
 |   CompileSuccessfully(str); | 
 |   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); | 
 |   EXPECT_THAT(getDiagnosticString(), | 
 |               HasSubstr("Variables can not have a function[7] storage class " | 
 |                         "outside of a function")); | 
 | } | 
 |  | 
 | TEST_F(ValidateStorage, OtherStorageOutsideFunction) { | 
 |   char str[] = R"( | 
 |           OpCapability Shader | 
 |           OpCapability Kernel | 
 |           OpCapability AtomicStorage | 
 |           OpCapability Linkage | 
 |           OpMemoryModel Logical GLSL450 | 
 | %intt   = OpTypeInt 32 0 | 
 | %voidt  = OpTypeVoid | 
 | %vfunct = OpTypeFunction %voidt | 
 | %ptrt   = OpTypePointer Function %intt | 
 | %unicon = OpVariable %ptrt UniformConstant | 
 | %input  = OpVariable %ptrt Input | 
 | %unif   = OpVariable %ptrt Uniform | 
 | %output = OpVariable %ptrt Output | 
 | %wgroup = OpVariable %ptrt Workgroup | 
 | %xwgrp  = OpVariable %ptrt CrossWorkgroup | 
 | %priv   = OpVariable %ptrt Private | 
 | %pushco = OpVariable %ptrt PushConstant | 
 | %atomct = OpVariable %ptrt AtomicCounter | 
 | %image  = OpVariable %ptrt Image | 
 | %func   = OpFunction %voidt None %vfunct | 
 | %funcl  = OpLabel | 
 |           OpReturn | 
 |           OpFunctionEnd | 
 | )"; | 
 |  | 
 |   CompileSuccessfully(str); | 
 |   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); | 
 | } | 
 |  | 
 | // clang-format off | 
 | TEST_P(ValidateStorage, OtherStorageInsideFunction) { | 
 |   std::stringstream ss; | 
 |   ss << R"( | 
 |           OpCapability Shader | 
 |           OpCapability Kernel | 
 |           OpCapability AtomicStorage | 
 |           OpCapability Linkage | 
 |           OpMemoryModel Logical GLSL450 | 
 | %intt   = OpTypeInt 32 0 | 
 | %voidt  = OpTypeVoid | 
 | %vfunct = OpTypeFunction %voidt | 
 | %ptrt   = OpTypePointer Function %intt | 
 | %func   = OpFunction %voidt None %vfunct | 
 | %funcl  = OpLabel | 
 | %var    = OpVariable %ptrt )" << GetParam() << R"( | 
 |           OpReturn | 
 |           OpFunctionEnd | 
 | )"; | 
 |  | 
 |   CompileSuccessfully(ss.str()); | 
 |   ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); | 
 |   EXPECT_THAT(getDiagnosticString(), HasSubstr( | 
 |       "Variables must have a function[7] storage class inside of a function")); | 
 | } | 
 |  | 
 | INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateStorage, | 
 |                         ::testing::Values( | 
 |                              "Input", | 
 |                              "Uniform", | 
 |                              "Output", | 
 |                              "Workgroup", | 
 |                              "CrossWorkgroup", | 
 |                              "Private", | 
 |                              "PushConstant", | 
 |                              "AtomicCounter", | 
 |                              "Image"),); | 
 | // clang-format on | 
 |  | 
 | TEST_F(ValidateStorage, GenericVariableOutsideFunction) { | 
 |   const auto str = R"( | 
 |           OpCapability Kernel | 
 |           OpCapability Linkage | 
 |           OpMemoryModel Logical OpenCL | 
 | %intt   = OpTypeInt 32 0 | 
 | %ptrt   = OpTypePointer Function %intt | 
 | %var    = OpVariable %ptrt Generic | 
 | )"; | 
 |   CompileSuccessfully(str); | 
 |   ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); | 
 |   EXPECT_THAT(getDiagnosticString(), | 
 |               HasSubstr("OpVariable storage class cannot be Generic")); | 
 | } | 
 |  | 
 | TEST_F(ValidateStorage, GenericVariableInsideFunction) { | 
 |   const auto str = R"( | 
 |           OpCapability Shader | 
 |           OpCapability Linkage | 
 |           OpMemoryModel Logical GLSL450 | 
 | %intt   = OpTypeInt 32 1 | 
 | %voidt  = OpTypeVoid | 
 | %vfunct = OpTypeFunction %voidt | 
 | %ptrt   = OpTypePointer Function %intt | 
 | %func   = OpFunction %voidt None %vfunct | 
 | %funcl  = OpLabel | 
 | %var    = OpVariable %ptrt Generic | 
 |           OpReturn | 
 |           OpFunctionEnd | 
 | )"; | 
 |   CompileSuccessfully(str); | 
 |   ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); | 
 |   EXPECT_THAT(getDiagnosticString(), | 
 |               HasSubstr("OpVariable storage class cannot be Generic")); | 
 | } | 
 | } |