浏览代码

Fixed implicit conversions between arrays and structs

FXC considers arrays the same as structures for implicit conversions, so int[2] should be implicitly convertible to struct { int x; float y; }, for example.
Tristan Labelle 6 年之前
父节点
当前提交
cc42781591

+ 13 - 12
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -8042,6 +8042,7 @@ bool HLSLExternalSource::CanConvert(
   _Inout_opt_ StandardConversionSequence* standard)
 {
   UINT uTSize, uSSize;
+  bool SourceIsAggregate, TargetIsAggregate; // Early declarations due to gotos below
 
   DXASSERT_NOMSG(sourceExpr != nullptr);
   DXASSERT_NOMSG(!target.isNull());
@@ -8112,34 +8113,34 @@ bool HLSLExternalSource::CanConvert(
   }
 
   // Structure cast.
-  if (TargetInfo.ShapeKind == AR_TOBJ_COMPOUND || TargetInfo.ShapeKind == AR_TOBJ_ARRAY ||
-      SourceInfo.ShapeKind == AR_TOBJ_COMPOUND || SourceInfo.ShapeKind == AR_TOBJ_ARRAY) {
-    if (!explicitConversion && TargetInfo.ShapeKind != SourceInfo.ShapeKind)
+  SourceIsAggregate = SourceInfo.ShapeKind == AR_TOBJ_COMPOUND || SourceInfo.ShapeKind == AR_TOBJ_ARRAY;
+  TargetIsAggregate = TargetInfo.ShapeKind == AR_TOBJ_COMPOUND || TargetInfo.ShapeKind == AR_TOBJ_ARRAY;
+  if (SourceIsAggregate || TargetIsAggregate) {
+    // For implicit conversions, FXC treats arrays the same as structures
+    // and rejects conversions between them and numeric types
+    if (!explicitConversion && SourceIsAggregate != TargetIsAggregate)
     {
       return false;
     }
 
+    // Structure to structure cases
     const RecordType *targetRT = dyn_cast<RecordType>(target);
     const RecordType *sourceRT = dyn_cast<RecordType>(source);
     if (targetRT && sourceRT) {
       RecordDecl *targetRD = targetRT->getDecl();
       RecordDecl *sourceRD = sourceRT->getDecl();
-      const CXXRecordDecl *targetCXXRD = dyn_cast<CXXRecordDecl>(targetRD);
-      const CXXRecordDecl *sourceCXXRD = dyn_cast<CXXRecordDecl>(sourceRD);
-      if (targetCXXRD && sourceCXXRD) {
+      if (sourceRT && targetRT) {
         if (targetRD == sourceRD) {
           Second = ICK_Flat_Conversion;
           goto lSuccess;
         }
-        if (sourceCXXRD->isDerivedFrom(targetCXXRD)) {
+
+        const CXXRecordDecl* targetCXXRD = dyn_cast<CXXRecordDecl>(targetRD);
+        const CXXRecordDecl* sourceCXXRD = dyn_cast<CXXRecordDecl>(sourceRD);
+        if (targetCXXRD && sourceCXXRD && sourceCXXRD->isDerivedFrom(targetCXXRD)) {
           Second = ICK_HLSL_Derived_To_Base;
           goto lSuccess;
         }
-      } else {
-        if (targetRD == sourceRD) {
-          Second = ICK_Flat_Conversion;
-          goto lSuccess;
-        }
       }
     }
 

+ 8 - 8
tools/clang/test/CodeGenHLSL/expressions/conversions_and_casts/between_type_shapes.hlsl

@@ -120,9 +120,9 @@ void main()
     // DXC: i32 11, i32 0, i32 0, i32 0, i8 15)
     // FXC: l(11,0,0,0)
     output_a1((A1)m1x1);
-    // DXC rejects (GitHub #1862)
+    // DXC: i32 1, i32 0, i32 0, i32 0, i8 15)
     // FXC: l(1,0,0,0)
-    // output_a1(s1); 
+    output_a1(s1); 
     // DXC: i32 1, i32 0, i32 0, i32 0, i8 15)
     // FXC: l(1,0,0,0)
     output_a1((A1)s1);
@@ -136,9 +136,9 @@ void main()
     // DXC: i32 11, i32 0, i32 0, i32 0, i8 15)
     // FXC: l(11,0,0,0)
     output_s1((S1)m1x1);
-    // DXC rejects (GitHub #1862)
+    // DXC: i32 1, i32 0, i32 0, i32 0, i8 15)
     // FXC: l(1,0,0,0)
-    // output_s1(a1);
+    output_s1(a1);
     // DXC: i32 1, i32 0, i32 0, i32 0, i8 15)
     // FXC: l(1,0,0,0)
     output_s1((S1)a1);
@@ -307,9 +307,9 @@ void main()
     // DXC: i32 11, i32 12, i32 21, i32 22, i8 15)
     // FXC: l(11,12,21,22)
     output_a4((A4)m2x2);
-    // DXC rejects (GitHub #1862)
+    // DXC: i32 1, i32 2, i32 0, i32 0, i8 15)
     // FXC: l(1,2,0,0)
-    // output_a2(s2);
+    output_a2(s2);
     // DXC: i32 1, i32 2, i32 0, i32 0, i8 15)
     // FXC: l(1,2,0,0)
     output_a2((A2)s2);
@@ -326,9 +326,9 @@ void main()
     // DXC: i32 11, i32 12, i32 21, i32 22, i8 15)
     // FXC: l(11,12,21,22)
     output_s4((S4)m2x2);
-    // DXC rejects (GitHub #1862)
+    // DXC: i32 1, i32 2, i32 0, i32 0, i8 15)
     // FXC: l(1,2,0,0)
-    // output_s2(a2);
+    output_s2(a2);
     // DXC: i32 1, i32 2, i32 0, i32 0, i8 15)
     // FXC: l(1,2,0,0)
     output_s2((S2)a2);

+ 4 - 4
tools/clang/test/HLSL/conversions-between-type-shapes.hlsl

@@ -87,7 +87,7 @@ void main()
     (A1)v1;
     to_a1(m1x1);                                            /* expected-error {{no matching function for call to 'to_a1'}} fxc-error {{X3017: 'to_a1': cannot convert from 'int1' to 'typedef int[1]'}} */
     (A1)m1x1;
-    to_a1(s1);                                              /* expected-error {{no matching function for call to 'to_a1'}} fxc-pass {{}} */
+    to_a1(s1);
     (A1)s1;
 
     to_s1(i);                                               /* expected-error {{no matching function for call to 'to_s1'}} fxc-error {{X3017: 'to_s1': cannot convert from 'int' to 'struct S1'}} */
@@ -96,7 +96,7 @@ void main()
     (S1)v1;
     to_s1(m1x1);                                            /* expected-error {{no matching function for call to 'to_s1'}} fxc-error {{X3017: 'to_s1': cannot convert from 'int1' to 'struct S1'}} */
     (S1)m1x1;
-    to_s1(a1);                                              /* expected-error {{no matching function for call to 'to_s1'}} fxc-pass {{}} */
+    to_s1(a1);
     (S1)a1;
 
     // =========== Truncation to scalar/single-element ===========
@@ -204,7 +204,7 @@ void main()
     (A2)m2x1;
     to_a4(m2x2);                                            /* expected-error {{no matching function for call to 'to_a4'}} fxc-error {{X3017: 'to_a4': cannot convert from 'int2x2' to 'typedef int[4]'}} */
     (A4)m2x2;
-    to_a2(s2);                                              /* expected-error {{no matching function for call to 'to_a2'}} fxc-pass {{}} */
+    to_a2(s2);
     (A2)s2;
 
     to_s2(v2);                                              /* expected-error {{no matching function for call to 'to_s2'}} fxc-error {{X3017: 'to_s2': cannot convert from 'int2' to 'struct S2'}} */
@@ -215,7 +215,7 @@ void main()
     (S2)m2x1;
     to_s4(m2x2);                                            /* expected-error {{no matching function for call to 'to_s4'}} fxc-error {{X3017: 'to_s4': cannot convert from 'int2x2' to 'struct S4'}} */
     (S4)m2x2;
-    to_s2(a2);                                              /* expected-error {{no matching function for call to 'to_s2'}} fxc-pass {{}} */
+    to_s2(a2);
     (S2)a2;
 
     // =========== Truncating ===========