[clang] [llvm] [HLSL] Implement '__builtin_hlsl_is_intangible' type trait (PR #104544)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 4 12:08:13 PDT 2024
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/104544
>From 6d5f8991a4ef9e79bc1bed30addf7b29b7ed0d2e Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 15 Aug 2024 19:03:29 -0700
Subject: [PATCH 01/16] Implement `__builtin_is_intangible`
---
clang/include/clang/Basic/TokenKinds.def | 3 ++
clang/include/clang/Sema/SemaHLSL.h | 3 ++
clang/lib/Sema/SemaExprCXX.cpp | 8 ++++
clang/lib/Sema/SemaHLSL.cpp | 49 ++++++++++++++++++++++++
4 files changed, 63 insertions(+)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index d683106bb0e298..f4fc7c321d9c5a 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -660,6 +660,9 @@ KEYWORD(out , KEYHLSL)
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL)
#include "clang/Basic/HLSLIntangibleTypes.def"
+// HLSL Type traits
+TYPE_TRAIT_1(__builtin_is_intangible, IsIntangibleType, 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 d60cb2a57d4918..13e75a79ec6bf0 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -62,6 +62,9 @@ class SemaHLSL : public SemaBase {
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ // HLSL Type trait implementations
+ bool IsIntangibleType(QualType T1) const;
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 5356bcf172f752..f3f8d511a6e568 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -39,6 +39,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/SemaObjC.h"
@@ -5683,6 +5684,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return true;
return false;
}
+ case UTT_IsIntangibleType:
+ if (!T->isVoidType() && !T->isIncompleteArrayType())
+ if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
+ diag::err_incomplete_type))
+ return true;
+ DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_is_intangible);
+ return Self.HLSL().IsIntangibleType(T);
}
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e3e926465e799e..5978c14399ba32 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -1154,3 +1155,51 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
return false;
}
+
+bool SemaHLSL::IsIntangibleType(QualType Ty) const {
+ if (Ty.isNull())
+ return false;
+
+ Ty = Ty.getCanonicalType().getUnqualifiedType();
+ if (Ty->isBuiltinType())
+ return Ty->isHLSLSpecificType();
+
+ llvm::SmallVector<QualType, 8> TypesToScan;
+ TypesToScan.push_back(Ty);
+ while (!TypesToScan.empty()) {
+ QualType T = TypesToScan.pop_back_val();
+ assert(T == T.getCanonicalType().getUnqualifiedType() && "expected sugar-free type");
+ assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
+
+ if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
+ QualType ElTy = AT->getElementType().getCanonicalType().getUnqualifiedType();
+ if (ElTy->isBuiltinType())
+ return ElTy->isHLSLSpecificType();
+ TypesToScan.push_back(ElTy);
+ continue;
+ }
+
+ if (const auto *VT = dyn_cast<VectorType>(T)) {
+ QualType ElTy = VT->getElementType().getCanonicalType().getUnqualifiedType();
+ assert(ElTy->isBuiltinType() && "vectors can only contain builtin types");
+ if (ElTy->isHLSLSpecificType())
+ return true;
+ continue;
+ }
+
+ if (const auto *RT = dyn_cast<RecordType>(T)) {
+ const RecordDecl *RD = RT->getDecl();
+ for (const auto *FD : RD->fields()) {
+ QualType FieldTy = FD->getType().getCanonicalType().getUnqualifiedType();
+ if (FieldTy->isBuiltinType()) {
+ if (FieldTy->isHLSLSpecificType())
+ return true;
+ } else {
+ TypesToScan.push_back(FieldTy);
+ }
+ }
+ continue;
+ }
+ }
+ return false;
+}
>From d21ca2e2891acbd6c89864b57d864d881a8a8b96 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 15 Aug 2024 20:52:24 -0700
Subject: [PATCH 02/16] add caching
---
clang/include/clang/Sema/SemaHLSL.h | 5 ++++-
clang/lib/Sema/SemaExprCXX.cpp | 1 +
clang/lib/Sema/SemaHLSL.cpp | 22 +++++++++++++++++-----
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 13e75a79ec6bf0..663dea12880d1b 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -64,7 +64,10 @@ class SemaHLSL : public SemaBase {
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
// HLSL Type trait implementations
- bool IsIntangibleType(QualType T1) const;
+ bool IsIntangibleType(const QualType T1);
+
+private:
+ llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache;
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f3f8d511a6e568..d3964f5da01e00 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5099,6 +5099,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
case UTT_IsTriviallyDestructible:
+ case UTT_IsIntangibleType:
if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
return true;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5978c14399ba32..e23240a380528d 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -28,7 +28,7 @@
using namespace clang;
-SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {}
+SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache(8) {}
Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
SourceLocation KwLoc, IdentifierInfo *Ident,
@@ -1156,10 +1156,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return false;
}
-bool SemaHLSL::IsIntangibleType(QualType Ty) const {
- if (Ty.isNull())
- return false;
-
+static bool calculateIsIntangibleType(QualType Ty) {
Ty = Ty.getCanonicalType().getUnqualifiedType();
if (Ty->isBuiltinType())
return Ty->isHLSLSpecificType();
@@ -1203,3 +1200,18 @@ bool SemaHLSL::IsIntangibleType(QualType Ty) const {
}
return false;
}
+
+bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) {
+ if (Ty.isNull())
+ return false;
+
+ const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr());
+ if (CachedEntry != IsIntangibleTypeCache.end()) {
+ assert(CachedEntry->second == calculateIsIntangibleType(Ty) && "IsIntangibleType mismatch");
+ return CachedEntry->second;
+ }
+
+ bool IsIntangible = calculateIsIntangibleType(Ty);
+ IsIntangibleTypeCache[Ty.getTypePtr()] = IsIntangible;
+ return IsIntangible;
+}
>From d7e8bce2e27f894196691435d2379edfdd6cd906 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 15 Aug 2024 20:56:40 -0700
Subject: [PATCH 03/16] clang-format
---
clang/lib/Sema/SemaHLSL.cpp | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e23240a380528d..5e5917c40bc1cc 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1165,19 +1165,22 @@ static bool calculateIsIntangibleType(QualType Ty) {
TypesToScan.push_back(Ty);
while (!TypesToScan.empty()) {
QualType T = TypesToScan.pop_back_val();
- assert(T == T.getCanonicalType().getUnqualifiedType() && "expected sugar-free type");
+ assert(T == T.getCanonicalType().getUnqualifiedType() &&
+ "expected sugar-free type");
assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
- QualType ElTy = AT->getElementType().getCanonicalType().getUnqualifiedType();
+ QualType ElTy =
+ AT->getElementType().getCanonicalType().getUnqualifiedType();
if (ElTy->isBuiltinType())
return ElTy->isHLSLSpecificType();
TypesToScan.push_back(ElTy);
- continue;
+ continue;
}
if (const auto *VT = dyn_cast<VectorType>(T)) {
- QualType ElTy = VT->getElementType().getCanonicalType().getUnqualifiedType();
+ QualType ElTy =
+ VT->getElementType().getCanonicalType().getUnqualifiedType();
assert(ElTy->isBuiltinType() && "vectors can only contain builtin types");
if (ElTy->isHLSLSpecificType())
return true;
@@ -1187,12 +1190,13 @@ static bool calculateIsIntangibleType(QualType Ty) {
if (const auto *RT = dyn_cast<RecordType>(T)) {
const RecordDecl *RD = RT->getDecl();
for (const auto *FD : RD->fields()) {
- QualType FieldTy = FD->getType().getCanonicalType().getUnqualifiedType();
+ QualType FieldTy =
+ FD->getType().getCanonicalType().getUnqualifiedType();
if (FieldTy->isBuiltinType()) {
if (FieldTy->isHLSLSpecificType())
return true;
} else {
- TypesToScan.push_back(FieldTy);
+ TypesToScan.push_back(FieldTy);
}
}
continue;
@@ -1207,7 +1211,8 @@ bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) {
const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr());
if (CachedEntry != IsIntangibleTypeCache.end()) {
- assert(CachedEntry->second == calculateIsIntangibleType(Ty) && "IsIntangibleType mismatch");
+ assert(CachedEntry->second == calculateIsIntangibleType(Ty) &&
+ "IsIntangibleType mismatch");
return CachedEntry->second;
}
>From 481c118d7d94f16c9cc9babbaaa794f951883088 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 15 Aug 2024 21:16:19 -0700
Subject: [PATCH 04/16] add tests
---
.../Types/Traits/IsIntangibleType.hlsl | 52 +++++++++++++++++++
.../Types/Traits/IsIntangibleTypeErrors.hlsl | 11 ++++
2 files changed, 63 insertions(+)
create mode 100644 clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
create mode 100644 clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
new file mode 100644
index 00000000000000..ae6da681d5100e
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+// expected-no-diagnostics
+
+_Static_assert(__builtin_is_intangible(__hlsl_resource_t), "");
+// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported
+
+_Static_assert(!__builtin_is_intangible(int), "");
+_Static_assert(!__builtin_is_intangible(float3), "");
+_Static_assert(!__builtin_is_intangible(half[4]), "");
+
+typedef __hlsl_resource_t Res;
+_Static_assert(__builtin_is_intangible(const Res), "");
+// no need to check array of Res, arrays of sizeless types are not supported
+
+struct ABuffer {
+ const int i[10];
+ __hlsl_resource_t h;
+};
+_Static_assert(__builtin_is_intangible(ABuffer), "");
+_Static_assert(__builtin_is_intangible(ABuffer[10]), "");
+
+struct MyStruct {
+ half2 h2;
+ int3 i3;
+};
+_Static_assert(!__builtin_is_intangible(MyStruct), "");
+_Static_assert(!__builtin_is_intangible(MyStruct[10]), "");
+
+class MyClass {
+ int3 ivec;
+ float farray[12];
+ MyStruct ms;
+ ABuffer buf;
+};
+_Static_assert(__builtin_is_intangible(MyClass), "");
+_Static_assert(__builtin_is_intangible(MyClass[2]), "");
+
+union U {
+ double d[4];
+ Res buf;
+};
+_Static_assert(__builtin_is_intangible(U), "");
+_Static_assert(__builtin_is_intangible(U[100]), "");
+
+class MyClass2 {
+ int3 ivec;
+ float farray[12];
+ U u;
+};
+_Static_assert(__builtin_is_intangible(MyClass2), "");
+_Static_assert(__builtin_is_intangible(MyClass2[5]), "");
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
new file mode 100644
index 00000000000000..bfb654de0dcfca
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
+
+struct Undefined; // expected-note {{forward declaration of 'Undefined'}}
+_Static_assert(!__builtin_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}}
+
+void fn(int X) {
+ // expected-error@#vla {{variable length arrays are not supported for the current target}}
+ // expected-error@#vla {{variable length arrays are not supported in '__builtin_is_intangible'}}
+ // expected-warning@#vla {{variable length arrays in C++ are a Clang extension}}
+ _Static_assert(!__builtin_is_intangible(int[X]), ""); // #vla
+}
\ No newline at end of file
>From 2df05761de1df378cedec49430c327a21f8ee089 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 15 Aug 2024 21:56:28 -0700
Subject: [PATCH 05/16] base classes!
---
clang/lib/Sema/SemaHLSL.cpp | 21 +++++++++++--------
.../Types/Traits/IsIntangibleType.hlsl | 9 ++++++++
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5e5917c40bc1cc..09d4d6e7f13c72 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -10,6 +10,7 @@
#include "clang/Sema/SemaHLSL.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
@@ -1157,7 +1158,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
static bool calculateIsIntangibleType(QualType Ty) {
- Ty = Ty.getCanonicalType().getUnqualifiedType();
+ Ty = Ty->getCanonicalTypeUnqualified();
if (Ty->isBuiltinType())
return Ty->isHLSLSpecificType();
@@ -1165,13 +1166,11 @@ static bool calculateIsIntangibleType(QualType Ty) {
TypesToScan.push_back(Ty);
while (!TypesToScan.empty()) {
QualType T = TypesToScan.pop_back_val();
- assert(T == T.getCanonicalType().getUnqualifiedType() &&
- "expected sugar-free type");
+ assert(T == T->getCanonicalTypeUnqualified() && "expected sugar-free type");
assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
- QualType ElTy =
- AT->getElementType().getCanonicalType().getUnqualifiedType();
+ QualType ElTy = AT->getElementType()->getCanonicalTypeUnqualified();
if (ElTy->isBuiltinType())
return ElTy->isHLSLSpecificType();
TypesToScan.push_back(ElTy);
@@ -1179,8 +1178,7 @@ static bool calculateIsIntangibleType(QualType Ty) {
}
if (const auto *VT = dyn_cast<VectorType>(T)) {
- QualType ElTy =
- VT->getElementType().getCanonicalType().getUnqualifiedType();
+ QualType ElTy = VT->getElementType()->getCanonicalTypeUnqualified();
assert(ElTy->isBuiltinType() && "vectors can only contain builtin types");
if (ElTy->isHLSLSpecificType())
return true;
@@ -1190,8 +1188,7 @@ static bool calculateIsIntangibleType(QualType Ty) {
if (const auto *RT = dyn_cast<RecordType>(T)) {
const RecordDecl *RD = RT->getDecl();
for (const auto *FD : RD->fields()) {
- QualType FieldTy =
- FD->getType().getCanonicalType().getUnqualifiedType();
+ QualType FieldTy = FD->getType()->getCanonicalTypeUnqualified();
if (FieldTy->isBuiltinType()) {
if (FieldTy->isHLSLSpecificType())
return true;
@@ -1199,6 +1196,12 @@ static bool calculateIsIntangibleType(QualType Ty) {
TypesToScan.push_back(FieldTy);
}
}
+
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (const CXXBaseSpecifier &B : CXXRD->bases()) {
+ TypesToScan.push_back(B.getType()->getCanonicalTypeUnqualified());
+ }
+ }
continue;
}
}
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
index ae6da681d5100e..f7ef7f543bfb5e 100644
--- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
@@ -50,3 +50,12 @@ class MyClass2 {
};
_Static_assert(__builtin_is_intangible(MyClass2), "");
_Static_assert(__builtin_is_intangible(MyClass2[5]), "");
+
+class Simple {
+ int a;
+};
+
+class MyClass3 : MyClass2, Simple {
+ half h;
+};
+_Static_assert(__builtin_is_intangible(MyClass3), "");
>From 227befd3ecff7899ef0088045176cead79aa8adc Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 15 Aug 2024 22:26:44 -0700
Subject: [PATCH 06/16] Update default for incomplete type
---
clang/lib/Sema/SemaExprCXX.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d3964f5da01e00..94132a4823e305 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5689,7 +5689,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (!T->isVoidType() && !T->isIncompleteArrayType())
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
- return true;
+ return false;
DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_is_intangible);
return Self.HLSL().IsIntangibleType(T);
}
>From 4bbf083bd75de42c82e4b2068b541241fcd492fd Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Mon, 19 Aug 2024 15:04:58 -0700
Subject: [PATCH 07/16] Rename to `__builtin_hlsl_is_intangible`
---
clang/include/clang/Basic/TokenKinds.def | 2 +-
clang/lib/Sema/SemaExprCXX.cpp | 2 +-
.../Types/Traits/IsIntangibleType.hlsl | 32 +++++++++----------
.../Types/Traits/IsIntangibleTypeErrors.hlsl | 6 ++--
4 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index f4fc7c321d9c5a..1b36d799f13f46 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -661,7 +661,7 @@ KEYWORD(out , KEYHLSL)
#include "clang/Basic/HLSLIntangibleTypes.def"
// HLSL Type traits
-TYPE_TRAIT_1(__builtin_is_intangible, IsIntangibleType, KEYHLSL)
+TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL)
// OpenMP Type Traits
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 94132a4823e305..55366bfd20b100 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5690,7 +5690,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
return false;
- DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_is_intangible);
+ DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_hlsl_is_intangible);
return Self.HLSL().IsIntangibleType(T);
}
}
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
index f7ef7f543bfb5e..39a912f99d3896 100644
--- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
@@ -2,30 +2,30 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
// expected-no-diagnostics
-_Static_assert(__builtin_is_intangible(__hlsl_resource_t), "");
+_Static_assert(__builtin_hlsl_is_intangible(__hlsl_resource_t), "");
// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported
-_Static_assert(!__builtin_is_intangible(int), "");
-_Static_assert(!__builtin_is_intangible(float3), "");
-_Static_assert(!__builtin_is_intangible(half[4]), "");
+_Static_assert(!__builtin_hlsl_is_intangible(int), "");
+_Static_assert(!__builtin_hlsl_is_intangible(float3), "");
+_Static_assert(!__builtin_hlsl_is_intangible(half[4]), "");
typedef __hlsl_resource_t Res;
-_Static_assert(__builtin_is_intangible(const Res), "");
+_Static_assert(__builtin_hlsl_is_intangible(const Res), "");
// no need to check array of Res, arrays of sizeless types are not supported
struct ABuffer {
const int i[10];
__hlsl_resource_t h;
};
-_Static_assert(__builtin_is_intangible(ABuffer), "");
-_Static_assert(__builtin_is_intangible(ABuffer[10]), "");
+_Static_assert(__builtin_hlsl_is_intangible(ABuffer), "");
+_Static_assert(__builtin_hlsl_is_intangible(ABuffer[10]), "");
struct MyStruct {
half2 h2;
int3 i3;
};
-_Static_assert(!__builtin_is_intangible(MyStruct), "");
-_Static_assert(!__builtin_is_intangible(MyStruct[10]), "");
+_Static_assert(!__builtin_hlsl_is_intangible(MyStruct), "");
+_Static_assert(!__builtin_hlsl_is_intangible(MyStruct[10]), "");
class MyClass {
int3 ivec;
@@ -33,23 +33,23 @@ class MyClass {
MyStruct ms;
ABuffer buf;
};
-_Static_assert(__builtin_is_intangible(MyClass), "");
-_Static_assert(__builtin_is_intangible(MyClass[2]), "");
+_Static_assert(__builtin_hlsl_is_intangible(MyClass), "");
+_Static_assert(__builtin_hlsl_is_intangible(MyClass[2]), "");
union U {
double d[4];
Res buf;
};
-_Static_assert(__builtin_is_intangible(U), "");
-_Static_assert(__builtin_is_intangible(U[100]), "");
+_Static_assert(__builtin_hlsl_is_intangible(U), "");
+_Static_assert(__builtin_hlsl_is_intangible(U[100]), "");
class MyClass2 {
int3 ivec;
float farray[12];
U u;
};
-_Static_assert(__builtin_is_intangible(MyClass2), "");
-_Static_assert(__builtin_is_intangible(MyClass2[5]), "");
+_Static_assert(__builtin_hlsl_is_intangible(MyClass2), "");
+_Static_assert(__builtin_hlsl_is_intangible(MyClass2[5]), "");
class Simple {
int a;
@@ -58,4 +58,4 @@ class Simple {
class MyClass3 : MyClass2, Simple {
half h;
};
-_Static_assert(__builtin_is_intangible(MyClass3), "");
+_Static_assert(__builtin_hlsl_is_intangible(MyClass3), "");
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
index bfb654de0dcfca..bbf2a1682e3f05 100644
--- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
struct Undefined; // expected-note {{forward declaration of 'Undefined'}}
-_Static_assert(!__builtin_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}}
+_Static_assert(!__builtin_hlsl_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}}
void fn(int X) {
// expected-error@#vla {{variable length arrays are not supported for the current target}}
- // expected-error@#vla {{variable length arrays are not supported in '__builtin_is_intangible'}}
+ // expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}}
// expected-warning@#vla {{variable length arrays in C++ are a Clang extension}}
- _Static_assert(!__builtin_is_intangible(int[X]), ""); // #vla
+ _Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla
}
\ No newline at end of file
>From 6fd1bf74d532160338bf8b091a15e06369c37027 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Mon, 19 Aug 2024 17:52:07 -0700
Subject: [PATCH 08/16] clang-format
---
clang/lib/Sema/SemaExprCXX.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 55366bfd20b100..49942944c37806 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5690,7 +5690,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
return false;
- DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_hlsl_is_intangible);
+ DiagnoseVLAInCXXTypeTrait(Self, TInfo,
+ tok::kw___builtin_hlsl_is_intangible);
return Self.HLSL().IsIntangibleType(T);
}
}
>From 7f29d6fe8f7ca5fac9dfb475fc256b82b3b64048 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 27 Aug 2024 12:29:29 -0700
Subject: [PATCH 09/16] Address code review feedback
---
clang/include/clang/AST/Type.h | 7 ++
clang/include/clang/Sema/SemaHLSL.h | 6 +-
clang/lib/Sema/SemaExprCXX.cpp | 1 +
clang/lib/Sema/SemaHLSL.cpp | 19 ++--
particle_life.hlsl | 147 ++++++++++++++++++++++++++++
5 files changed, 171 insertions(+), 9 deletions(-)
create mode 100644 particle_life.hlsl
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 575f3c17a3f691..d19e353967fa8b 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2656,6 +2656,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) bool is##Id##Type() const;
#include "clang/Basic/HLSLIntangibleTypes.def"
bool isHLSLSpecificType() const; // Any HLSL specific type
+ bool isHLSLIntangibleType() const; // Any HLSL intangible type
/// Determines if this type, which must satisfy
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
@@ -8286,6 +8287,12 @@ inline bool Type::isHLSLSpecificType() const {
false; // end boolean or operation
}
+inline bool Type::isHLSLIntangibleType() const {
+ // All HLSL specific types are currently intangible type as well, but that
+ // might change in the future.
+ return isHLSLSpecificType();
+}
+
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType);
}
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index e923df60b91458..cae3a502c73cf0 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -62,12 +62,12 @@ class SemaHLSL : public SemaBase {
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-private:
- llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache;
-
// HLSL Type trait implementations
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
bool IsIntangibleType(const QualType T1);
+
+private:
+ llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache;
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 7e179bc9939cdd..4c7c6bfdb2db9d 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5697,6 +5697,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
}
case UTT_IsIntangibleType:
+ assert(Self.getLangOpts().HLSL && "intangible types are HLSL-only feature");
if (!T->isVoidType() && !T->isIncompleteArrayType())
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e939fca1411a5d..f7cf18be195f3f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -29,7 +29,7 @@
using namespace clang;
-SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache(8) {}
+SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache() {}
Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
SourceLocation KwLoc, IdentifierInfo *Ident,
@@ -1528,11 +1528,10 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
static bool calculateIsIntangibleType(QualType Ty) {
- Ty = Ty->getCanonicalTypeUnqualified();
- if (Ty->isBuiltinType())
- return Ty->isHLSLSpecificType();
+ assert(!Ty.getCanonicalType().getUnqualifiedType()->isBuiltinType() &&
+ "builtin types should be taken care of in IsIntangibleType");
- llvm::SmallVector<QualType, 8> TypesToScan;
+ llvm::SmallVector<QualType> TypesToScan;
TypesToScan.push_back(Ty);
while (!TypesToScan.empty()) {
QualType T = TypesToScan.pop_back_val();
@@ -1582,6 +1581,12 @@ bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) {
if (Ty.isNull())
return false;
+ // check if it's a builtin type first (simple check, no need to cache it)
+ QualType CT = Ty->getCanonicalTypeUnqualified();
+ if (CT->isBuiltinType())
+ return CT->isHLSLIntangibleType();
+
+ // more complex type -> check if we already have it in the cache
const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr());
if (CachedEntry != IsIntangibleTypeCache.end()) {
assert(CachedEntry->second == calculateIsIntangibleType(Ty) &&
@@ -1589,9 +1594,12 @@ bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) {
return CachedEntry->second;
}
+ // calculate and add to cache
bool IsIntangible = calculateIsIntangibleType(Ty);
IsIntangibleTypeCache[Ty.getTypePtr()] = IsIntangible;
return IsIntangible;
+}
+
static void BuildFlattenedTypeList(QualType BaseTy,
llvm::SmallVectorImpl<QualType> &List) {
llvm::SmallVector<QualType, 16> WorkList;
@@ -1673,4 +1681,3 @@ bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
return SemaRef.IsLayoutCompatible(LHS, RHS);
});
}
-}
diff --git a/particle_life.hlsl b/particle_life.hlsl
new file mode 100644
index 00000000000000..4cffbdb04e1b60
--- /dev/null
+++ b/particle_life.hlsl
@@ -0,0 +1,147 @@
+#define ROOT_SIGNATURE \
+ "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)," \
+ "CBV(b0)," \
+ "SRV(t0)," \
+ "SRV(t1)," \
+ "UAV(u0)," \
+ "UAV(u1)"
+
+
+cbuffer CONSTANTS : register(b0) {
+ uint ParticleTypeMax;
+ uint NumParticles;
+ float2 WorldSize;
+ float Friction;
+ float ForceMultipler;
+}
+
+struct Rule {
+ float force;
+ float min_distance;
+ float max_distance;
+};
+
+struct Particle {
+ float2 position;
+ float2 velocity;
+ uint type;
+};
+
+struct Vertex {
+ float2 position;
+ uint color;
+};
+
+StructuredBuffer<Rule> Rules : register(t0);
+StructuredBuffer<Particle> OldParticles : register(t1);
+RWStructuredBuffer<Particle> NewParticles : register(u0);
+RWStructuredBuffer<Vertex> Vertices : register(u1);
+
+
+float3 particle_type_to_color(uint type);
+uint float_to_abgr(float3 rgb);
+
+
+[numthreads(32, 1, 1)]
+void main(uint3 dispatch_thread_id : SV_DispatchThreadID) {
+ uint particle_id = dispatch_thread_id.x;
+
+ Particle particle = OldParticles[particle_id];
+
+ // Accumulate forces
+ float2 force = float2(0,0);
+ float hit = 0;
+
+ for (uint i = 0; i < NumParticles; ++i) {
+ if (i == particle_id)
+ continue;
+
+ Particle other_particle = OldParticles[i];
+
+ Rule rule = Rules[particle.type * ParticleTypeMax + other_particle.type];
+
+ float2 direction = other_particle.position - particle.position;
+
+ // wrapping
+ if (direction.x > WorldSize.x * 0.5f)
+ direction.x -= WorldSize.x;
+ if (direction.x < WorldSize.x * -0.5f)
+ direction.x += WorldSize.x;
+ if (direction.y > WorldSize.y * 0.5f)
+ direction.y -= WorldSize.y;
+ if (direction.y < WorldSize.y * -0.5f)
+ direction.y += WorldSize.y;
+
+ // apply rule
+ float distance = length(direction);
+ direction = normalize(direction);
+
+ if (distance < rule.min_distance) {
+ float repulsive_amount = abs(rule.force) * (1.0f - (distance / rule.min_distance)) * -3.0f;
+ force += direction * repulsive_amount;
+ }
+
+ if (distance < rule.max_distance) {
+ float attract_amount = rule.force * (1.0f - (distance / rule.max_distance));
+ force += direction * attract_amount;
+ hit += 0.01f;
+ }
+ }
+
+ float2 velocity = particle.velocity;
+ velocity += force * ForceMultipler;
+ velocity *= Friction;
+
+ particle.position = particle.position + velocity;
+
+ if (particle.position.x < 0)
+ particle.position.x += WorldSize.x;
+
+ if (particle.position.x > WorldSize.x)
+ particle.position.x -= WorldSize.x;
+
+ if (particle.position.y < 0)
+ particle.position.y += WorldSize.y;
+
+ if (particle.position.y > WorldSize.y)
+ particle.position.y -= WorldSize.y;
+
+
+ particle.velocity = velocity;
+
+ Vertices[particle_id].position = particle.position;
+
+ float3 color = particle_type_to_color(particle.type);
+
+ color = lerp(color, color * 0.1f, 1-saturate(hit));
+
+ Vertices[particle_id].color = float_to_abgr(color);
+
+ NewParticles[particle_id] = particle;
+}
+
+
+
+// from https://chilliant.com/rgb2hsv.html
+float3 hue2rgb(float H) {
+ float R = abs(H * 6 - 3) - 1;
+ float G = 2 - abs(H * 6 - 2);
+ float B = 2 - abs(H * 6 - 4);
+ return saturate(float3(R,G,B));
+}
+
+float3 particle_type_to_color(uint type) {
+ float hue = (float)type / float(ParticleTypeMax);
+ return hue2rgb(hue);
+}
+
+uint float_to_abgr(float3 rgb) {
+ rgb *= 255.0;
+
+ uint r = rgb.x;
+ uint g = rgb.y;
+ uint b = rgb.z;
+ uint a = 255;
+
+ return (a << 24) | (b << 16) | (g << 8) | r;
+}
\ No newline at end of file
>From d666eb7999c43e2cd6ae9c0948a6e0380bb1d425 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 27 Aug 2024 12:53:48 -0700
Subject: [PATCH 10/16] Remove accidentally added file
---
particle_life.hlsl | 147 ---------------------------------------------
1 file changed, 147 deletions(-)
delete mode 100644 particle_life.hlsl
diff --git a/particle_life.hlsl b/particle_life.hlsl
deleted file mode 100644
index 4cffbdb04e1b60..00000000000000
--- a/particle_life.hlsl
+++ /dev/null
@@ -1,147 +0,0 @@
-#define ROOT_SIGNATURE \
- "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)," \
- "CBV(b0)," \
- "SRV(t0)," \
- "SRV(t1)," \
- "UAV(u0)," \
- "UAV(u1)"
-
-
-cbuffer CONSTANTS : register(b0) {
- uint ParticleTypeMax;
- uint NumParticles;
- float2 WorldSize;
- float Friction;
- float ForceMultipler;
-}
-
-struct Rule {
- float force;
- float min_distance;
- float max_distance;
-};
-
-struct Particle {
- float2 position;
- float2 velocity;
- uint type;
-};
-
-struct Vertex {
- float2 position;
- uint color;
-};
-
-StructuredBuffer<Rule> Rules : register(t0);
-StructuredBuffer<Particle> OldParticles : register(t1);
-RWStructuredBuffer<Particle> NewParticles : register(u0);
-RWStructuredBuffer<Vertex> Vertices : register(u1);
-
-
-float3 particle_type_to_color(uint type);
-uint float_to_abgr(float3 rgb);
-
-
-[numthreads(32, 1, 1)]
-void main(uint3 dispatch_thread_id : SV_DispatchThreadID) {
- uint particle_id = dispatch_thread_id.x;
-
- Particle particle = OldParticles[particle_id];
-
- // Accumulate forces
- float2 force = float2(0,0);
- float hit = 0;
-
- for (uint i = 0; i < NumParticles; ++i) {
- if (i == particle_id)
- continue;
-
- Particle other_particle = OldParticles[i];
-
- Rule rule = Rules[particle.type * ParticleTypeMax + other_particle.type];
-
- float2 direction = other_particle.position - particle.position;
-
- // wrapping
- if (direction.x > WorldSize.x * 0.5f)
- direction.x -= WorldSize.x;
- if (direction.x < WorldSize.x * -0.5f)
- direction.x += WorldSize.x;
- if (direction.y > WorldSize.y * 0.5f)
- direction.y -= WorldSize.y;
- if (direction.y < WorldSize.y * -0.5f)
- direction.y += WorldSize.y;
-
- // apply rule
- float distance = length(direction);
- direction = normalize(direction);
-
- if (distance < rule.min_distance) {
- float repulsive_amount = abs(rule.force) * (1.0f - (distance / rule.min_distance)) * -3.0f;
- force += direction * repulsive_amount;
- }
-
- if (distance < rule.max_distance) {
- float attract_amount = rule.force * (1.0f - (distance / rule.max_distance));
- force += direction * attract_amount;
- hit += 0.01f;
- }
- }
-
- float2 velocity = particle.velocity;
- velocity += force * ForceMultipler;
- velocity *= Friction;
-
- particle.position = particle.position + velocity;
-
- if (particle.position.x < 0)
- particle.position.x += WorldSize.x;
-
- if (particle.position.x > WorldSize.x)
- particle.position.x -= WorldSize.x;
-
- if (particle.position.y < 0)
- particle.position.y += WorldSize.y;
-
- if (particle.position.y > WorldSize.y)
- particle.position.y -= WorldSize.y;
-
-
- particle.velocity = velocity;
-
- Vertices[particle_id].position = particle.position;
-
- float3 color = particle_type_to_color(particle.type);
-
- color = lerp(color, color * 0.1f, 1-saturate(hit));
-
- Vertices[particle_id].color = float_to_abgr(color);
-
- NewParticles[particle_id] = particle;
-}
-
-
-
-// from https://chilliant.com/rgb2hsv.html
-float3 hue2rgb(float H) {
- float R = abs(H * 6 - 3) - 1;
- float G = 2 - abs(H * 6 - 2);
- float B = 2 - abs(H * 6 - 4);
- return saturate(float3(R,G,B));
-}
-
-float3 particle_type_to_color(uint type) {
- float hue = (float)type / float(ParticleTypeMax);
- return hue2rgb(hue);
-}
-
-uint float_to_abgr(float3 rgb) {
- rgb *= 255.0;
-
- uint r = rgb.x;
- uint g = rgb.y;
- uint b = rgb.z;
- uint a = 255;
-
- return (a << 24) | (b << 16) | (g << 8) | r;
-}
\ No newline at end of file
>From dcd2c494f9d9fa33e2631e2e19609c3d6167c5cd Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 27 Aug 2024 13:15:16 -0700
Subject: [PATCH 11/16] Simplify IsIntangible calculation, add empty new line
---
clang/lib/Sema/SemaHLSL.cpp | 48 ++++++++++---------
.../Types/Traits/IsIntangibleTypeErrors.hlsl | 2 +-
2 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f7cf18be195f3f..d907462c583976 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1534,42 +1534,44 @@ static bool calculateIsIntangibleType(QualType Ty) {
llvm::SmallVector<QualType> TypesToScan;
TypesToScan.push_back(Ty);
while (!TypesToScan.empty()) {
- QualType T = TypesToScan.pop_back_val();
- assert(T == T->getCanonicalTypeUnqualified() && "expected sugar-free type");
- assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL");
+ QualType T = TypesToScan.pop_back_val()->getCanonicalTypeUnqualified();
+
+ if (T->isBuiltinType()) {
+ if (T->isHLSLIntangibleType())
+ return true;
+ }
if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
- QualType ElTy = AT->getElementType()->getCanonicalTypeUnqualified();
- if (ElTy->isBuiltinType())
- return ElTy->isHLSLSpecificType();
- TypesToScan.push_back(ElTy);
+ TypesToScan.push_back(AT->getElementType());
continue;
}
if (const auto *VT = dyn_cast<VectorType>(T)) {
- QualType ElTy = VT->getElementType()->getCanonicalTypeUnqualified();
- assert(ElTy->isBuiltinType() && "vectors can only contain builtin types");
- if (ElTy->isHLSLSpecificType())
- return true;
+ assert(!VT->getElementType()
+ .getCanonicalType()
+ .getUnqualifiedType()
+ ->isHLSLIntangibleType() &&
+ "vectors can only contain builtin types that are not intangible");
+ continue;
+ }
+
+ if (const auto *MT = dyn_cast<MatrixType>(T)) {
+ assert(!MT->getElementType()
+ .getCanonicalType()
+ .getUnqualifiedType()
+ ->isHLSLIntangibleType() &&
+ "matrices can only contain builtin types that are not intangible");
continue;
}
if (const auto *RT = dyn_cast<RecordType>(T)) {
const RecordDecl *RD = RT->getDecl();
- for (const auto *FD : RD->fields()) {
- QualType FieldTy = FD->getType()->getCanonicalTypeUnqualified();
- if (FieldTy->isBuiltinType()) {
- if (FieldTy->isHLSLSpecificType())
- return true;
- } else {
- TypesToScan.push_back(FieldTy);
- }
- }
+ for (const auto *FD : RD->fields())
+ TypesToScan.push_back(FD->getType());
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
- for (const CXXBaseSpecifier &B : CXXRD->bases()) {
- TypesToScan.push_back(B.getType()->getCanonicalTypeUnqualified());
- }
+ for (const CXXBaseSpecifier &B : CXXRD->bases())
+ TypesToScan.push_back(B.getType());
}
continue;
}
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
index bbf2a1682e3f05..0803086749bd7d 100644
--- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl
@@ -8,4 +8,4 @@ void fn(int X) {
// expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}}
// expected-warning@#vla {{variable length arrays in C++ are a Clang extension}}
_Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla
-}
\ No newline at end of file
+}
>From 97ffb26613a44e19cb1d74ef090128291d1776e9 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 3 Sep 2024 16:21:46 -0700
Subject: [PATCH 12/16] Replace DenseMap cache with 2 bits on
RecordDeclBitfields
---
clang/include/clang/AST/Decl.h | 6 +++
clang/include/clang/AST/DeclBase.h | 15 +++++++-
clang/include/clang/Sema/SemaHLSL.h | 5 +--
clang/lib/AST/Decl.cpp | 1 +
clang/lib/Sema/SemaHLSL.cpp | 57 ++++++++++++++++-------------
5 files changed, 54 insertions(+), 30 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 6d84bd03de810a..819b7eeeeab7fb 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -61,6 +61,7 @@ class Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class FunctionTypeLoc;
+enum class IntangibleResult : unsigned char;
class LabelStmt;
class MemberSpecializationInfo;
class Module;
@@ -4298,6 +4299,11 @@ class RecordDecl : public TagDecl {
void reorderDecls(const SmallVectorImpl<Decl *> &Decls);
+ // Intangible types
+ IntangibleResult getIntangible() const { return static_cast<IntangibleResult>(RecordDeclBits.Intangible); }
+
+ void setIntangible(IntangibleResult R) { RecordDeclBits.Intangible = llvm::to_underlying(R); }
+
/// Determines whether this declaration represents the
/// injected class name.
///
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index ee662ed73d7e0e..9f309be75d0ac1 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1411,6 +1411,15 @@ enum class DeductionCandidate : unsigned char {
Aggregate,
};
+enum class IntangibleResult : unsigned char {
+ // IsIntangible has not been computed.
+ Invalid = 0,
+ // Intangible type
+ Intangible,
+ // Not an intangible type
+ NotIntangible
+};
+
enum class RecordArgPassingKind;
enum class OMPDeclareReductionInitKind;
enum class ObjCImplementationControl;
@@ -1680,9 +1689,13 @@ class DeclContext {
LLVM_PREFERRED_TYPE(bool)
uint64_t IsRandomized : 1;
+ // Indicates whether this struct is intangible
+ LLVM_PREFERRED_TYPE(IntangibleResult)
+ uint64_t Intangible : 2;
+
/// True if a valid hash is stored in ODRHash. This should shave off some
/// extra storage and prevent CXXRecordDecl to store unused bits.
- uint64_t ODRHash : 26;
+ uint64_t ODRHash : 24;
};
/// Number of inherited and non-inherited bits in RecordDeclBitfields.
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index cae3a502c73cf0..ceb66fb71577a1 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -64,10 +64,7 @@ class SemaHLSL : public SemaBase {
// HLSL Type trait implementations
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
- bool IsIntangibleType(const QualType T1);
-
-private:
- llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache;
+ bool IsIntangibleType(QualType T1);
};
} // namespace clang
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1a07125815832e..0cea6a704df301 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5016,6 +5016,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
setParamDestroyedInCallee(false);
setArgPassingRestrictions(RecordArgPassingKind::CanPassInRegs);
setIsRandomized(false);
+ setIntangible(IntangibleResult::Invalid);
setODRHash(0);
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index d907462c583976..f301ccc079efd9 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -10,6 +10,7 @@
#include "clang/Sema/SemaHLSL.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
@@ -29,7 +30,7 @@
using namespace clang;
-SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache() {}
+SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {}
Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
SourceLocation KwLoc, IdentifierInfo *Ident,
@@ -1527,11 +1528,11 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return false;
}
-static bool calculateIsIntangibleType(QualType Ty) {
- assert(!Ty.getCanonicalType().getUnqualifiedType()->isBuiltinType() &&
+static bool calculateIsIntangibleType(const Type *Ty) {
+ assert(!Ty->isBuiltinType() &&
"builtin types should be taken care of in IsIntangibleType");
- llvm::SmallVector<QualType> TypesToScan;
+ llvm::SmallVector<const Type *> TypesToScan;
TypesToScan.push_back(Ty);
while (!TypesToScan.empty()) {
QualType T = TypesToScan.pop_back_val()->getCanonicalTypeUnqualified();
@@ -1542,7 +1543,7 @@ static bool calculateIsIntangibleType(QualType Ty) {
}
if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
- TypesToScan.push_back(AT->getElementType());
+ TypesToScan.push_back(AT->getElementType().getTypePtr());
continue;
}
@@ -1566,12 +1567,15 @@ static bool calculateIsIntangibleType(QualType Ty) {
if (const auto *RT = dyn_cast<RecordType>(T)) {
const RecordDecl *RD = RT->getDecl();
+ if (RD->getIntangible() == IntangibleResult::Intangible)
+ return true;
+
for (const auto *FD : RD->fields())
- TypesToScan.push_back(FD->getType());
+ TypesToScan.push_back(FD->getType().getTypePtr());
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const CXXBaseSpecifier &B : CXXRD->bases())
- TypesToScan.push_back(B.getType());
+ TypesToScan.push_back(B.getType().getTypePtr());
}
continue;
}
@@ -1579,27 +1583,30 @@ static bool calculateIsIntangibleType(QualType Ty) {
return false;
}
-bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) {
- if (Ty.isNull())
+bool SemaHLSL::IsIntangibleType(clang::QualType QT) {
+ if (QT.isNull())
return false;
// check if it's a builtin type first (simple check, no need to cache it)
- QualType CT = Ty->getCanonicalTypeUnqualified();
- if (CT->isBuiltinType())
- return CT->isHLSLIntangibleType();
-
- // more complex type -> check if we already have it in the cache
- const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr());
- if (CachedEntry != IsIntangibleTypeCache.end()) {
- assert(CachedEntry->second == calculateIsIntangibleType(Ty) &&
- "IsIntangibleType mismatch");
- return CachedEntry->second;
- }
-
- // calculate and add to cache
- bool IsIntangible = calculateIsIntangibleType(Ty);
- IsIntangibleTypeCache[Ty.getTypePtr()] = IsIntangible;
- return IsIntangible;
+ const Type *Ty = QT->getCanonicalTypeUnqualified()->getTypePtr();
+ if (Ty->isBuiltinType())
+ return Ty->isHLSLIntangibleType();
+
+ while (isa<ConstantArrayType>(Ty))
+ Ty = Ty->getArrayElementTypeNoTypeQual();
+
+ const RecordType *RT = dyn_cast<RecordType>(Ty);
+ if (!RT)
+ return false;
+
+ RecordDecl *RD = RT->getAsRecordDecl();
+ IntangibleResult Result = RD->getIntangible();
+ if (Result == IntangibleResult::Invalid) {
+ Result = calculateIsIntangibleType(Ty) ? IntangibleResult::Intangible
+ : IntangibleResult::NotIntangible;
+ RD->setIntangible(Result);
+ }
+ return Result == IntangibleResult::Intangible;
}
static void BuildFlattenedTypeList(QualType BaseTy,
>From 094e208326f22ac063069cfcf0924186d4ba5845 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 3 Sep 2024 23:06:10 -0700
Subject: [PATCH 13/16] Store IsIntangible in CXXRecordDecl flags; set it when
new field or base class is added
---
.../clang/AST/CXXRecordDeclDefinitionBits.def | 4 ++
clang/include/clang/AST/Decl.h | 6 --
clang/include/clang/AST/DeclBase.h | 15 +---
clang/include/clang/AST/DeclCXX.h | 4 ++
clang/lib/AST/Decl.cpp | 1 -
clang/lib/AST/DeclCXX.cpp | 17 ++++-
clang/lib/Sema/SemaHLSL.cpp | 70 ++-----------------
.../Types/Traits/IsIntangibleType.hlsl | 23 +++++-
8 files changed, 52 insertions(+), 88 deletions(-)
diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
index cdf0804680ad0a..48830109b6b6a8 100644
--- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
+++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -249,4 +249,8 @@ FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR)
/// base classes or fields have a no-return destructor
FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
+/// Whether the record type is intangible (if any base classes or fields have
+/// type that is intangible). HLSL only.
+FIELD(IsIntangible, 1, NO_MERGE)
+
#undef FIELD
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 9ab9528baceda8..0600ecc4d14a18 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -61,7 +61,6 @@ class Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class FunctionTypeLoc;
-enum class IntangibleResult : unsigned char;
class LabelStmt;
class MemberSpecializationInfo;
class Module;
@@ -4300,11 +4299,6 @@ class RecordDecl : public TagDecl {
void reorderDecls(const SmallVectorImpl<Decl *> &Decls);
- // Intangible types
- IntangibleResult getIntangible() const { return static_cast<IntangibleResult>(RecordDeclBits.Intangible); }
-
- void setIntangible(IntangibleResult R) { RecordDeclBits.Intangible = llvm::to_underlying(R); }
-
/// Determines whether this declaration represents the
/// injected class name.
///
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 9f309be75d0ac1..ee662ed73d7e0e 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1411,15 +1411,6 @@ enum class DeductionCandidate : unsigned char {
Aggregate,
};
-enum class IntangibleResult : unsigned char {
- // IsIntangible has not been computed.
- Invalid = 0,
- // Intangible type
- Intangible,
- // Not an intangible type
- NotIntangible
-};
-
enum class RecordArgPassingKind;
enum class OMPDeclareReductionInitKind;
enum class ObjCImplementationControl;
@@ -1689,13 +1680,9 @@ class DeclContext {
LLVM_PREFERRED_TYPE(bool)
uint64_t IsRandomized : 1;
- // Indicates whether this struct is intangible
- LLVM_PREFERRED_TYPE(IntangibleResult)
- uint64_t Intangible : 2;
-
/// True if a valid hash is stored in ODRHash. This should shave off some
/// extra storage and prevent CXXRecordDecl to store unused bits.
- uint64_t ODRHash : 24;
+ uint64_t ODRHash : 26;
};
/// Number of inherited and non-inherited bits in RecordDeclBitfields.
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 0d72cc6a08dcb4..b46422d4a5f3c2 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1547,6 +1547,10 @@ class CXXRecordDecl : public RecordDecl {
/// destructors are marked noreturn.
bool isAnyDestructorNoReturn() const { return data().IsAnyDestructorNoReturn; }
+ /// Returns true if the class contains HLSL intangible type, either as
+ /// a field or in base class.
+ bool isIntangible() const { return data().IsIntangible; }
+
/// If the class is a local class [class.local], returns
/// the enclosing function declaration.
const FunctionDecl *isLocalClass() const {
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 0cea6a704df301..1a07125815832e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -5016,7 +5016,6 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
setParamDestroyedInCallee(false);
setArgPassingRestrictions(RecordArgPassingKind::CanPassInRegs);
setIsRandomized(false);
- setIntangible(IntangibleResult::Invalid);
setODRHash(0);
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 9a3ede426e9143..b3721a19344a0b 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -109,7 +109,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
HasDeclaredCopyAssignmentWithConstParam(false),
- IsAnyDestructorNoReturn(false), IsLambda(false),
+ IsAnyDestructorNoReturn(false), IsIntangible(false), IsLambda(false),
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
HasODRHash(false), Definition(D) {}
@@ -431,6 +431,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (BaseClassDecl->isAnyDestructorNoReturn())
data().IsAnyDestructorNoReturn = true;
+ if (BaseClassDecl->isIntangible())
+ data().IsIntangible = true;
+
// C++11 [class.copy]p18:
// The implicitly-declared copy assignment operator for a class X will
// have the form 'X& X::operator=(const X&)' if each direct base class B
@@ -1401,6 +1404,18 @@ void CXXRecordDecl::addedMember(Decl *D) {
// than subobjects of zero size
if (data().Empty && !IsZeroSize)
data().Empty = false;
+
+ if (getLangOpts().HLSL) {
+ const Type* Ty = Field->getType().getTypePtr();
+ while (isa<ConstantArrayType>(Ty))
+ Ty = Ty->getArrayElementTypeNoTypeQual();
+
+ Ty = Ty->getUnqualifiedDesugaredType();
+ if (Ty->isBuiltinType())
+ data().IsIntangible |= Ty->isHLSLIntangibleType();
+ else if (const RecordType *RT = dyn_cast<RecordType>(Ty))
+ data().IsIntangible |= RT->getAsCXXRecordDecl()->isIntangible();
+ }
}
// Handle using declarations of conversion functions.
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a04cdae2d47c5d..93629e6b25bd24 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1612,85 +1612,29 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return false;
}
-static bool calculateIsIntangibleType(const Type *Ty) {
- assert(!Ty->isBuiltinType() &&
- "builtin types should be taken care of in IsIntangibleType");
- llvm::SmallVector<const Type *> TypesToScan;
- TypesToScan.push_back(Ty);
- while (!TypesToScan.empty()) {
- QualType T = TypesToScan.pop_back_val()->getCanonicalTypeUnqualified();
-
- if (T->isBuiltinType()) {
- if (T->isHLSLIntangibleType())
- return true;
- }
-
- if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {
- TypesToScan.push_back(AT->getElementType().getTypePtr());
- continue;
- }
-
- if (const auto *VT = dyn_cast<VectorType>(T)) {
- assert(!VT->getElementType()
- .getCanonicalType()
- .getUnqualifiedType()
- ->isHLSLIntangibleType() &&
- "vectors can only contain builtin types that are not intangible");
- continue;
- }
-
- if (const auto *MT = dyn_cast<MatrixType>(T)) {
- assert(!MT->getElementType()
- .getCanonicalType()
- .getUnqualifiedType()
- ->isHLSLIntangibleType() &&
- "matrices can only contain builtin types that are not intangible");
- continue;
- }
-
- if (const auto *RT = dyn_cast<RecordType>(T)) {
- const RecordDecl *RD = RT->getDecl();
- if (RD->getIntangible() == IntangibleResult::Intangible)
- return true;
-
- for (const auto *FD : RD->fields())
- TypesToScan.push_back(FD->getType().getTypePtr());
-
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
- for (const CXXBaseSpecifier &B : CXXRD->bases())
- TypesToScan.push_back(B.getType().getTypePtr());
- }
- continue;
- }
- }
- return false;
-}
bool SemaHLSL::IsIntangibleType(clang::QualType QT) {
if (QT.isNull())
return false;
+
+ const Type *Ty = QT->getUnqualifiedDesugaredType();
// check if it's a builtin type first (simple check, no need to cache it)
- const Type *Ty = QT->getCanonicalTypeUnqualified()->getTypePtr();
if (Ty->isBuiltinType())
return Ty->isHLSLIntangibleType();
+ // unwrap arrays
while (isa<ConstantArrayType>(Ty))
Ty = Ty->getArrayElementTypeNoTypeQual();
- const RecordType *RT = dyn_cast<RecordType>(Ty);
+ const RecordType *RT = dyn_cast<RecordType>(Ty->getUnqualifiedDesugaredType());
if (!RT)
return false;
- RecordDecl *RD = RT->getAsRecordDecl();
- IntangibleResult Result = RD->getIntangible();
- if (Result == IntangibleResult::Invalid) {
- Result = calculateIsIntangibleType(Ty) ? IntangibleResult::Intangible
- : IntangibleResult::NotIntangible;
- RD->setIntangible(Result);
- }
- return Result == IntangibleResult::Intangible;
+ CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
+ assert(RD != nullptr && "all HLSL struct and classes should be CXXRecordDecl");
+ return RD->isIntangible();
}
static void BuildFlattenedTypeList(QualType BaseTy,
diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
index 39a912f99d3896..92cba1dcd4bdfe 100644
--- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
+++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl
@@ -55,7 +55,24 @@ class Simple {
int a;
};
-class MyClass3 : MyClass2, Simple {
- half h;
+template<typename T> struct TemplatedBuffer {
+ T a;
+ __hlsl_resource_t h;
+};
+_Static_assert(__builtin_hlsl_is_intangible(TemplatedBuffer<int>), "");
+
+struct MyStruct2 : TemplatedBuffer<float> {
+ float x;
+};
+_Static_assert(__builtin_hlsl_is_intangible(MyStruct2), "");
+
+struct MyStruct3 {
+ const TemplatedBuffer<float> TB[10];
+};
+_Static_assert(__builtin_hlsl_is_intangible(MyStruct3), "");
+
+template<typename T> struct SimpleTemplate {
+ T a;
};
-_Static_assert(__builtin_hlsl_is_intangible(MyClass3), "");
+_Static_assert(__builtin_hlsl_is_intangible(SimpleTemplate<__hlsl_resource_t>), "");
+_Static_assert(!__builtin_hlsl_is_intangible(SimpleTemplate<float>), "");
>From 0e1b82c86f6baf2788de36b1dfa9e6770ee42a03 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 3 Sep 2024 23:19:31 -0700
Subject: [PATCH 14/16] clang-format & desugar
---
clang/include/clang/AST/DeclCXX.h | 2 +-
clang/lib/AST/DeclCXX.cpp | 2 +-
clang/lib/Sema/SemaHLSL.cpp | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index b46422d4a5f3c2..88277ec5fbc667 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1547,7 +1547,7 @@ class CXXRecordDecl : public RecordDecl {
/// destructors are marked noreturn.
bool isAnyDestructorNoReturn() const { return data().IsAnyDestructorNoReturn; }
- /// Returns true if the class contains HLSL intangible type, either as
+ /// Returns true if the class contains HLSL intangible type, either as
/// a field or in base class.
bool isIntangible() const { return data().IsIntangible; }
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index b3721a19344a0b..e1d640fb7fd33f 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1406,7 +1406,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().Empty = false;
if (getLangOpts().HLSL) {
- const Type* Ty = Field->getType().getTypePtr();
+ const Type *Ty = Field->getType()->getUnqualifiedDesugaredType();
while (isa<ConstantArrayType>(Ty))
Ty = Ty->getArrayElementTypeNoTypeQual();
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 93629e6b25bd24..141be788f9deb4 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1612,8 +1612,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return false;
}
-
-
bool SemaHLSL::IsIntangibleType(clang::QualType QT) {
if (QT.isNull())
return false;
@@ -1628,12 +1626,14 @@ bool SemaHLSL::IsIntangibleType(clang::QualType QT) {
while (isa<ConstantArrayType>(Ty))
Ty = Ty->getArrayElementTypeNoTypeQual();
- const RecordType *RT = dyn_cast<RecordType>(Ty->getUnqualifiedDesugaredType());
+ const RecordType *RT =
+ dyn_cast<RecordType>(Ty->getUnqualifiedDesugaredType());
if (!RT)
return false;
CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
- assert(RD != nullptr && "all HLSL struct and classes should be CXXRecordDecl");
+ assert(RD != nullptr &&
+ "all HLSL struct and classes should be CXXRecordDecl");
return RD->isIntangible();
}
>From 2eba03c682d1e5b05b7497982e1840f96b00f5ad Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 3 Sep 2024 23:27:27 -0700
Subject: [PATCH 15/16] one more little space
---
clang/lib/Sema/SemaHLSL.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 141be788f9deb4..cd7c4d14c3842b 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1615,7 +1615,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
bool SemaHLSL::IsIntangibleType(clang::QualType QT) {
if (QT.isNull())
return false;
-
+
const Type *Ty = QT->getUnqualifiedDesugaredType();
// check if it's a builtin type first (simple check, no need to cache it)
>From 027d473d082a9cd1799579212fc95316ff12fe54 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 4 Sep 2024 12:07:45 -0700
Subject: [PATCH 16/16] Rename to IsHLSLIntangible; return false for variable
length arrays after diag
---
.../include/clang/AST/CXXRecordDeclDefinitionBits.def | 2 +-
clang/include/clang/AST/DeclCXX.h | 2 +-
clang/lib/AST/DeclCXX.cpp | 10 +++++-----
clang/lib/Sema/SemaExprCXX.cpp | 5 +++--
clang/lib/Sema/SemaHLSL.cpp | 2 +-
5 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
index 48830109b6b6a8..6620840df0ced2 100644
--- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
+++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -251,6 +251,6 @@ FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
/// Whether the record type is intangible (if any base classes or fields have
/// type that is intangible). HLSL only.
-FIELD(IsIntangible, 1, NO_MERGE)
+FIELD(IsHLSLIntangible, 1, NO_MERGE)
#undef FIELD
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 88277ec5fbc667..252e6e92564142 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1549,7 +1549,7 @@ class CXXRecordDecl : public RecordDecl {
/// Returns true if the class contains HLSL intangible type, either as
/// a field or in base class.
- bool isIntangible() const { return data().IsIntangible; }
+ bool isHLSLIntangible() const { return data().IsHLSLIntangible; }
/// If the class is a local class [class.local], returns
/// the enclosing function declaration.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index e1d640fb7fd33f..01143391edab40 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -109,7 +109,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
HasDeclaredCopyAssignmentWithConstParam(false),
- IsAnyDestructorNoReturn(false), IsIntangible(false), IsLambda(false),
+ IsAnyDestructorNoReturn(false), IsHLSLIntangible(false), IsLambda(false),
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
HasODRHash(false), Definition(D) {}
@@ -431,8 +431,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (BaseClassDecl->isAnyDestructorNoReturn())
data().IsAnyDestructorNoReturn = true;
- if (BaseClassDecl->isIntangible())
- data().IsIntangible = true;
+ if (BaseClassDecl->isHLSLIntangible())
+ data().IsHLSLIntangible = true;
// C++11 [class.copy]p18:
// The implicitly-declared copy assignment operator for a class X will
@@ -1412,9 +1412,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
Ty = Ty->getUnqualifiedDesugaredType();
if (Ty->isBuiltinType())
- data().IsIntangible |= Ty->isHLSLIntangibleType();
+ data().IsHLSLIntangible |= Ty->isHLSLIntangibleType();
else if (const RecordType *RT = dyn_cast<RecordType>(Ty))
- data().IsIntangible |= RT->getAsCXXRecordDecl()->isIntangible();
+ data().IsHLSLIntangible |= RT->getAsCXXRecordDecl()->isHLSLIntangible();
}
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 467fc5048c164f..14feafd1e6b17f 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5703,8 +5703,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
return false;
- DiagnoseVLAInCXXTypeTrait(Self, TInfo,
- tok::kw___builtin_hlsl_is_intangible);
+ if (DiagnoseVLAInCXXTypeTrait(Self, TInfo,
+ tok::kw___builtin_hlsl_is_intangible))
+ return false;
return Self.HLSL().IsIntangibleType(T);
}
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index cd7c4d14c3842b..65aeda4b7b613e 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1634,7 +1634,7 @@ bool SemaHLSL::IsIntangibleType(clang::QualType QT) {
CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
assert(RD != nullptr &&
"all HLSL struct and classes should be CXXRecordDecl");
- return RD->isIntangible();
+ return RD->isHLSLIntangible();
}
static void BuildFlattenedTypeList(QualType BaseTy,
More information about the cfe-commits
mailing list