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 <heko...@microsoft.com> Date: Thu, 15 Aug 2024 19:03:29 -0700 Subject: [PATCH 01/15] 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 <heko...@microsoft.com> Date: Thu, 15 Aug 2024 20:52:24 -0700 Subject: [PATCH 02/15] 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 <heko...@microsoft.com> Date: Thu, 15 Aug 2024 20:56:40 -0700 Subject: [PATCH 03/15] 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 <heko...@microsoft.com> Date: Thu, 15 Aug 2024 21:16:19 -0700 Subject: [PATCH 04/15] 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 <heko...@microsoft.com> Date: Thu, 15 Aug 2024 21:56:28 -0700 Subject: [PATCH 05/15] 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 <heko...@microsoft.com> Date: Thu, 15 Aug 2024 22:26:44 -0700 Subject: [PATCH 06/15] 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 <heko...@microsoft.com> Date: Mon, 19 Aug 2024 15:04:58 -0700 Subject: [PATCH 07/15] 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 <heko...@microsoft.com> Date: Mon, 19 Aug 2024 17:52:07 -0700 Subject: [PATCH 08/15] 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 <heko...@microsoft.com> Date: Tue, 27 Aug 2024 12:29:29 -0700 Subject: [PATCH 09/15] 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 <heko...@microsoft.com> Date: Tue, 27 Aug 2024 12:53:48 -0700 Subject: [PATCH 10/15] 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 <heko...@microsoft.com> Date: Tue, 27 Aug 2024 13:15:16 -0700 Subject: [PATCH 11/15] 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 <heko...@microsoft.com> Date: Tue, 3 Sep 2024 16:21:46 -0700 Subject: [PATCH 12/15] 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 <heko...@microsoft.com> Date: Tue, 3 Sep 2024 23:06:10 -0700 Subject: [PATCH 13/15] 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 <heko...@microsoft.com> Date: Tue, 3 Sep 2024 23:19:31 -0700 Subject: [PATCH 14/15] 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 <heko...@microsoft.com> Date: Tue, 3 Sep 2024 23:27:27 -0700 Subject: [PATCH 15/15] 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) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits