Skip to content

[HLSL] add IsTypedResourceElementCompatible type trait #114864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 5, 2024

Conversation

bob80905
Copy link
Contributor

@bob80905 bob80905 commented Nov 4, 2024

This PR implements a new type trait as a builtin, __builtin_hlsl_is_typed_resource_element_compatible
This type traits verifies that the given input type is suitable as a typed resource element type.
It checks that the given input type is homogeneous, has no more than 4 sub elements, does not exceed 16 bytes, and does not contain any arrays, booleans, or enums.
Fixes an issue in #113730 that needed to cause that PR to be reverted.
Fixes #113223

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" HLSL HLSL Language Support labels Nov 4, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2024

@llvm/pr-subscribers-hlsl

Author: Joshua Batista (bob80905)

Changes

This PR implements a new type trait as a builtin, __builtin_hlsl_is_typed_resource_element_compatible
This type traits verifies that the given input type is suitable as a typed resource element type.
It checks that the given input type is homogeneous, has no more than 4 sub elements, does not exceed 16 bytes, and does not contain any arrays, booleans, or enums.
Fixes #113223


Full diff: https://github.com/llvm/llvm-project/pull/114864.diff

6 Files Affected:

  • (modified) clang/include/clang/Basic/TokenKinds.def (+1)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+1)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+10)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+44)
  • (added) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl (+101)
  • (added) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl (+10)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index fdfb35de9cf287..2c692c999bdff5 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -662,6 +662,7 @@ KEYWORD(out                         , KEYHLSL)
 // HLSL Type traits
 TYPE_TRAIT_2(__builtin_hlsl_is_scalarized_layout_compatible, IsScalarizedLayoutCompatible, KEYHLSL)
 TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL)
+TYPE_TRAIT_1(__builtin_hlsl_is_typed_resource_element_compatible, IsTypedResourceElementCompatible, KEYHLSL)
 
 // OpenMP Type Traits
 UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index e30acd87f77218..06c541dec08cc8 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -132,6 +132,7 @@ class SemaHLSL : public SemaBase {
 
   // HLSL Type trait implementations
   bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
+  bool IsTypedResourceElementCompatible(QualType T1);
 
   bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);
 
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 50c1b24fce6da7..0001e343da84be 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5032,6 +5032,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
   case UTT_IsScalar:
   case UTT_IsCompound:
   case UTT_IsMemberPointer:
+  case UTT_IsTypedResourceElementCompatible:
     // Fall-through
 
     // These traits are modeled on type predicates in C++0x [meta.unary.prop]
@@ -5714,6 +5715,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
                                   tok::kw___builtin_hlsl_is_intangible))
       return false;
     return T->isHLSLIntangibleType();
+
+  case UTT_IsTypedResourceElementCompatible:
+    assert(Self.getLangOpts().HLSL &&
+           "line vector layout compatible types are HLSL-only feature");
+    if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
+                                 diag::err_incomplete_type))
+      return false;
+
+    return Self.HLSL().IsTypedResourceElementCompatible(T);
   }
 }
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 1f6c5b8d4561bc..b4cd4aa9c85afd 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2163,6 +2163,50 @@ static void BuildFlattenedTypeList(QualType BaseTy,
   }
 }
 
+bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) {
+  if (QT.isNull())
+    return false;
+
+  // check if the outer type was an array type
+  if (QT->isArrayType())
+    return false;
+
+  llvm::SmallVector<QualType, 4> QTTypes;
+  BuildFlattenedTypeList(QT, QTTypes);
+
+  assert(QTTypes.size() > 0 &&
+         "expected at least one constituent type from non-null type");
+  QualType FirstQT = QTTypes[0];
+
+  // element count cannot exceed 4
+  if (QTTypes.size() > 4)
+    return false;
+
+  for (QualType TempQT : QTTypes) {
+    // ensure homogeneity
+    if (TempQT != FirstQT)
+      return false;
+
+    if (const BuiltinType *BT = TempQT->getAs<BuiltinType>()) {
+      if (BT->isBooleanType() || BT->isEnumeralType())
+        return false;
+
+      // Check if it is an array type.
+      if (TempQT->isArrayType())
+        return false;
+    }
+  }
+
+  // if the loop above completes without returning, then
+  // we've guaranteed homogeneity
+  int TotalSizeInBytes =
+      (SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size();
+  if (TotalSizeInBytes > 16)
+    return false;
+
+  return true;
+}
+
 bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
   if (T1.isNull() || T2.isNull())
     return false;
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
new file mode 100644
index 00000000000000..669c03ea39c8f7
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+// expected-no-diagnostics
+
+struct oneInt {
+    int i;
+};
+
+struct twoInt {
+   int aa;
+   int ab;
+};
+
+struct threeInts {
+  oneInt o;
+  twoInt t;
+};
+
+struct oneFloat {
+    float f;
+};
+struct depthDiff {
+  int i;
+  oneInt o;
+  oneFloat f;
+};
+
+struct notHomogenous{     
+  int i;
+  float f;
+};
+
+struct EightElements {
+  twoInt x[2];
+  twoInt y[2];
+};
+
+struct EightHalves {
+half x[8]; 
+};
+
+struct intVec {
+  int2 i;
+};
+
+struct oneIntWithVec {
+  int i;
+  oneInt i2;
+  int2 i3;
+};
+
+struct weirdStruct {
+  int i;
+  intVec iv;
+};
+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(int), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float4), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(double2), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneInt), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneFloat), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(twoInt), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(threeInts), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notHomogenous), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(depthDiff), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightElements), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightHalves), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneIntWithVec), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(weirdStruct), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(RWBuffer<int>), "");
+
+
+// arrays not allowed
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(half[4]), "");
+
+template<typename T> struct TemplatedBuffer {
+    T a;
+    __hlsl_resource_t h;
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(TemplatedBuffer<int>), "");
+
+struct MyStruct1 : TemplatedBuffer<float> {
+    float x;
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct1), "");
+
+struct MyStruct2 {
+    const TemplatedBuffer<float> TB[10];
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct2), "");
+
+template<typename T> struct SimpleTemplate {
+    T a;
+};
+
+// though the element type is incomplete, the type trait should still technically return true
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate<__hlsl_resource_t>), "");
+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate<float>), "");
+
+
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
new file mode 100644
index 00000000000000..167a5be6e93843
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+
+// types must be complete
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(__hlsl_resource_t), "");
+
+// expected-note@+1{{forward declaration of 'notComplete'}}
+struct notComplete;
+// expected-error@+1{{incomplete type 'notComplete' where a complete type is required}}
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notComplete), "");
+

@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2024

@llvm/pr-subscribers-clang

Author: Joshua Batista (bob80905)

Changes

This PR implements a new type trait as a builtin, __builtin_hlsl_is_typed_resource_element_compatible
This type traits verifies that the given input type is suitable as a typed resource element type.
It checks that the given input type is homogeneous, has no more than 4 sub elements, does not exceed 16 bytes, and does not contain any arrays, booleans, or enums.
Fixes #113223


Full diff: https://github.com/llvm/llvm-project/pull/114864.diff

6 Files Affected:

  • (modified) clang/include/clang/Basic/TokenKinds.def (+1)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+1)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+10)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+44)
  • (added) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl (+101)
  • (added) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl (+10)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index fdfb35de9cf287..2c692c999bdff5 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -662,6 +662,7 @@ KEYWORD(out                         , KEYHLSL)
 // HLSL Type traits
 TYPE_TRAIT_2(__builtin_hlsl_is_scalarized_layout_compatible, IsScalarizedLayoutCompatible, KEYHLSL)
 TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL)
+TYPE_TRAIT_1(__builtin_hlsl_is_typed_resource_element_compatible, IsTypedResourceElementCompatible, KEYHLSL)
 
 // OpenMP Type Traits
 UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index e30acd87f77218..06c541dec08cc8 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -132,6 +132,7 @@ class SemaHLSL : public SemaBase {
 
   // HLSL Type trait implementations
   bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
+  bool IsTypedResourceElementCompatible(QualType T1);
 
   bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);
 
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 50c1b24fce6da7..0001e343da84be 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5032,6 +5032,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
   case UTT_IsScalar:
   case UTT_IsCompound:
   case UTT_IsMemberPointer:
+  case UTT_IsTypedResourceElementCompatible:
     // Fall-through
 
     // These traits are modeled on type predicates in C++0x [meta.unary.prop]
@@ -5714,6 +5715,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
                                   tok::kw___builtin_hlsl_is_intangible))
       return false;
     return T->isHLSLIntangibleType();
+
+  case UTT_IsTypedResourceElementCompatible:
+    assert(Self.getLangOpts().HLSL &&
+           "line vector layout compatible types are HLSL-only feature");
+    if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
+                                 diag::err_incomplete_type))
+      return false;
+
+    return Self.HLSL().IsTypedResourceElementCompatible(T);
   }
 }
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 1f6c5b8d4561bc..b4cd4aa9c85afd 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2163,6 +2163,50 @@ static void BuildFlattenedTypeList(QualType BaseTy,
   }
 }
 
+bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) {
+  if (QT.isNull())
+    return false;
+
+  // check if the outer type was an array type
+  if (QT->isArrayType())
+    return false;
+
+  llvm::SmallVector<QualType, 4> QTTypes;
+  BuildFlattenedTypeList(QT, QTTypes);
+
+  assert(QTTypes.size() > 0 &&
+         "expected at least one constituent type from non-null type");
+  QualType FirstQT = QTTypes[0];
+
+  // element count cannot exceed 4
+  if (QTTypes.size() > 4)
+    return false;
+
+  for (QualType TempQT : QTTypes) {
+    // ensure homogeneity
+    if (TempQT != FirstQT)
+      return false;
+
+    if (const BuiltinType *BT = TempQT->getAs<BuiltinType>()) {
+      if (BT->isBooleanType() || BT->isEnumeralType())
+        return false;
+
+      // Check if it is an array type.
+      if (TempQT->isArrayType())
+        return false;
+    }
+  }
+
+  // if the loop above completes without returning, then
+  // we've guaranteed homogeneity
+  int TotalSizeInBytes =
+      (SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size();
+  if (TotalSizeInBytes > 16)
+    return false;
+
+  return true;
+}
+
 bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
   if (T1.isNull() || T2.isNull())
     return false;
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
new file mode 100644
index 00000000000000..669c03ea39c8f7
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+// expected-no-diagnostics
+
+struct oneInt {
+    int i;
+};
+
+struct twoInt {
+   int aa;
+   int ab;
+};
+
+struct threeInts {
+  oneInt o;
+  twoInt t;
+};
+
+struct oneFloat {
+    float f;
+};
+struct depthDiff {
+  int i;
+  oneInt o;
+  oneFloat f;
+};
+
+struct notHomogenous{     
+  int i;
+  float f;
+};
+
+struct EightElements {
+  twoInt x[2];
+  twoInt y[2];
+};
+
+struct EightHalves {
+half x[8]; 
+};
+
+struct intVec {
+  int2 i;
+};
+
+struct oneIntWithVec {
+  int i;
+  oneInt i2;
+  int2 i3;
+};
+
+struct weirdStruct {
+  int i;
+  intVec iv;
+};
+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(int), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float4), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(double2), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneInt), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneFloat), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(twoInt), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(threeInts), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notHomogenous), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(depthDiff), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightElements), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightHalves), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneIntWithVec), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(weirdStruct), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(RWBuffer<int>), "");
+
+
+// arrays not allowed
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(half[4]), "");
+
+template<typename T> struct TemplatedBuffer {
+    T a;
+    __hlsl_resource_t h;
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(TemplatedBuffer<int>), "");
+
+struct MyStruct1 : TemplatedBuffer<float> {
+    float x;
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct1), "");
+
+struct MyStruct2 {
+    const TemplatedBuffer<float> TB[10];
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct2), "");
+
+template<typename T> struct SimpleTemplate {
+    T a;
+};
+
+// though the element type is incomplete, the type trait should still technically return true
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate<__hlsl_resource_t>), "");
+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate<float>), "");
+
+
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
new file mode 100644
index 00000000000000..167a5be6e93843
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+
+// types must be complete
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(__hlsl_resource_t), "");
+
+// expected-note@+1{{forward declaration of 'notComplete'}}
+struct notComplete;
+// expected-error@+1{{incomplete type 'notComplete' where a complete type is required}}
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notComplete), "");
+

Copy link
Collaborator

@llvm-beanz llvm-beanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few additional test cases to add:

  • Empty struct types
  • typedef element types to something else, and mix the typedef and original type


case UTT_IsTypedResourceElementCompatible:
assert(Self.getLangOpts().HLSL &&
"line vector layout compatible types are HLSL-only feature");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"line vector layout compatible types are HLSL-only feature");
"typed resource element compatible types are HLSL-only feature");

llvm::SmallVector<QualType, 4> QTTypes;
BuildFlattenedTypeList(QT, QTTypes);

assert(QTTypes.size() > 0 &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this assert fire if QT is an empty struct?

Copy link
Contributor Author

@bob80905 bob80905 Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When QT is an empty struct (like struct notComplete; in clang\test\SemaHLSL\Types\Traits\IsTypedResourceElementCompatibleErrors.hlsl)
the assert is never hit, the function is never entered.
clang\lib\Sema\SemaExprCXX.cpp::EvaluateUnaryTypeTrait won't call IsTypedResourceElementCompatible because there's an early return, that is executed when RequireCompleteType returns false.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an incomplete type, not an empty struct. What about something like:

struct EmptyStruct {};
_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EmptyStruct), "");

struct EmptyDerived : EmptyStruct {};
_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EmptyDerived), "");

struct EmptyBase : EmptyStruct {
  int4 V;
};
_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(EmptyBase), "");

We frequently find bugs in DXC with cases of empty structs, empty base classes, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #115045

if (TempQT != FirstQT)
return false;

if (const BuiltinType *BT = TempQT->getAs<BuiltinType>()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than doing this in the loop for each type, you could do this after the loop on FirstQT, since all types need to be the same.


for (QualType TempQT : QTTypes) {
// ensure homogeneity
if (TempQT != FirstQT)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a call to hasSameUnqualifiedType not a direct comparison.


assert(QTTypes.size() > 0 &&
"expected at least one constituent type from non-null type");
QualType FirstQT = QTTypes[0];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll want to de-sugar this:

Suggested change
QualType FirstQT = QTTypes[0];
QualType FirstQT = SemaRef.Context.getCanonicalType(QTTypes[0]);

@bob80905 bob80905 merged commit b509eb7 into llvm:main Nov 5, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[HLSL] Create __builtin_hlsl_is_typed_resource_element_compatible builtin
3 participants