Просмотр исходного кода

Added an error for constant array indices being out of bounds. (#1931)

Out-of-bound array indices cause SROA to generate undef values. If returning that value, the finalize dxil pass will get rid of the storeOutput. See issue #1879

We do produce a warning on out-of-bounds errors, but FXC makes it an error and that's probably sensible due to the cascading effects of such undefs. We can only do that on constant expressions though, so the undef scenario can still happen for constant-valued indices resulting from later IR passes.
Tristan Labelle 6 лет назад
Родитель
Сommit
a4b240c85b

+ 2 - 0
tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

@@ -7440,6 +7440,8 @@ def err_opencl_constant_no_init : Error<
 
 // HLSL Change Starts
 let CategoryName = "HLSL Issue" in {
+def err_hlsl_array_element_index_out_of_bounds: Error<
+  "array element index '%0' is out of bounds">;
 def err_hlsl_attribute_expects_string_literal: Error<
   "attribute %0 must have a string literal argument">;
 def err_hlsl_attribute_expects_string_literal_from_list: Error<

+ 18 - 0
tools/clang/lib/Sema/SemaChecking.cpp

@@ -8468,6 +8468,14 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
       }
     }
 
+    // HLSL Change Starts
+    if (getLangOpts().HLSL) {
+      DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
+        PDiag(diag::err_hlsl_array_element_index_out_of_bounds) << index.toString(10, true));
+    }
+    else {
+    // HLSL Change Ends
+
     unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds;
     if (ASE)
       DiagID = diag::warn_array_index_exceeds_bounds;
@@ -8477,7 +8485,16 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
                           << size.toString(10, true)
                           << (unsigned)size.getLimitedValue(~0U)
                           << IndexExpr->getSourceRange());
+    } // HLSL Change
   } else {
+    // HLSL Change Starts
+    if (getLangOpts().HLSL) {
+      DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
+        PDiag(diag::err_hlsl_array_element_index_out_of_bounds) << index.toString(10, true));
+    }
+    else {
+    // HLSL Change Ends
+
     unsigned DiagID = diag::warn_array_index_precedes_bounds;
     if (!ASE) {
       DiagID = diag::warn_ptr_arith_precedes_bounds;
@@ -8487,6 +8504,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
     DiagRuntimeBehavior(BaseExpr->getLocStart(), BaseExpr,
                         PDiag(DiagID) << index.toString(10, true)
                           << IndexExpr->getSourceRange());
+    } // HLSL Change
   }
 
   if (!ND) {

+ 10 - 0
tools/clang/test/HLSL/array-index-out-of-bounds.hlsl

@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -Wno-unused-value -fsyntax-only -ffreestanding -verify -verify-ignore-unexpected=note %s
+
+void main()
+{
+    int array[2];
+    array[-1] = 0;                                          /* expected-error {{array element index '-1' is out of bounds}} fxc-error {{X3504: array index out of bounds}} */
+    array[0] = 0;
+    array[1] = 0;
+    array[2] = 0;                                           /* expected-error {{array element index '2' is out of bounds}} fxc-error {{X3504: array index out of bounds}} */
+}

+ 5 - 0
tools/clang/unittests/HLSL/VerifierTest.cpp

@@ -34,6 +34,7 @@ public:
     TEST_METHOD_PROPERTY(L"Priority", L"0")
   END_TEST_CLASS()
 
+  TEST_METHOD(RunArrayIndexOutOfBounds)
   TEST_METHOD(RunArrayLength)
   TEST_METHOD(RunAttributes)
   TEST_METHOD(RunBuiltinTypesNoInheritance)
@@ -136,6 +137,10 @@ public:
   }
 };
 
+TEST_F(VerifierTest, RunArrayIndexOutOfBounds) {
+  CheckVerifiesHLSL(L"array-index-out-of-bounds.hlsl");
+}
+
 TEST_F(VerifierTest, RunArrayLength) {
   CheckVerifiesHLSL(L"array-length.hlsl");
 }