[clang] [HLSL] Default and Relaxed Availability Diagnostics (PR #92704)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Tue May 28 13:53:18 PDT 2024
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/92704
>From 433b8e142d05a8fe2206ae0cec62423b21e792d2 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Sun, 19 May 2024 11:10:38 -0700
Subject: [PATCH 1/9] HLSL Default and Relaxed Availability Diagnostics (#3)
---
clang/include/clang/Basic/Attr.td | 52 +++
clang/include/clang/Basic/DiagnosticGroups.td | 3 +
.../clang/Basic/DiagnosticSemaKinds.td | 7 +
clang/include/clang/Sema/SemaHLSL.h | 1 +
clang/lib/Sema/Sema.cpp | 3 +
clang/lib/Sema/SemaAvailability.cpp | 14 +-
clang/lib/Sema/SemaHLSL.cpp | 296 ++++++++++++++++++
...attr-availability-shadermodel-compute.hlsl | 68 ++++
.../attr-availability-shadermodel-mesh.hlsl | 68 ++++
.../attr-availability-shadermodel-pixel.hlsl | 61 ++++
.../Sema/attr-availability-shadermodel.hlsl | 11 +
.../avail-diag-default-compute.hlsl | 98 ++++++
.../Availability/avail-diag-default-lib.hlsl | 108 +++++++
.../avail-diag-relaxed-compute.hlsl | 98 ++++++
.../Availability/avail-diag-relaxed-lib.hlsl | 108 +++++++
.../avail-lib-multiple-stages.hlsl | 57 ++++
.../SemaHLSL/WaveBuiltinAvailability.hlsl | 9 +-
17 files changed, 1056 insertions(+), 6 deletions(-)
create mode 100644 clang/test/Sema/attr-availability-shadermodel-compute.hlsl
create mode 100644 clang/test/Sema/attr-availability-shadermodel-mesh.hlsl
create mode 100644 clang/test/Sema/attr-availability-shadermodel-pixel.hlsl
create mode 100644 clang/test/Sema/attr-availability-shadermodel.hlsl
create mode 100644 clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
create mode 100644 clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
create mode 100644 clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
create mode 100644 clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
create mode 100644 clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 7008bea483c87..e5c23d54ab826 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1068,11 +1068,37 @@ static llvm::StringRef getPrettyEnviromentName(llvm::StringRef Environment) {
.Case("hull", "hull shader")
.Case("domain", "domain shader")
.Case("compute", "compute shader")
+ .Case("raygeneration", "ray generation shader")
+ .Case("intersection", "intersection shader")
+ .Case("anyhit", "anyhit shader")
+ .Case("closesthit", "closesthit shader")
+ .Case("miss", "miss shader")
+ .Case("callable", "callable shader")
.Case("mesh", "mesh shader")
.Case("amplification", "amplification shader")
.Case("library", "shader library")
.Default(Environment);
}
+static llvm::StringRef getEnvironmentString(llvm::Triple::EnvironmentType EnvironmentType) {
+ switch (EnvironmentType) {
+ case llvm::Triple::EnvironmentType::Pixel: return "pixel";
+ case llvm::Triple::EnvironmentType::Vertex: return "vertex";
+ case llvm::Triple::EnvironmentType::Geometry: return "geometry";
+ case llvm::Triple::EnvironmentType::Hull: return "hull";
+ case llvm::Triple::EnvironmentType::Domain: return "domain";
+ case llvm::Triple::EnvironmentType::Compute: return "compute";
+ case llvm::Triple::EnvironmentType::RayGeneration: return "ray generation";
+ case llvm::Triple::EnvironmentType::Intersection: return "intersection";
+ case llvm::Triple::EnvironmentType::AnyHit: return "any hit";
+ case llvm::Triple::EnvironmentType::ClosestHit: return "closest hit";
+ case llvm::Triple::EnvironmentType::Miss: return "miss";
+ case llvm::Triple::EnvironmentType::Callable: return "callable";
+ case llvm::Triple::EnvironmentType::Mesh: return "mesh";
+ case llvm::Triple::EnvironmentType::Amplification: return "amplification";
+ case llvm::Triple::EnvironmentType::Library: return "library";
+ default: return "";
+ }
+}
static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environment) {
return llvm::StringSwitch<llvm::Triple::EnvironmentType>(Environment)
.Case("pixel", llvm::Triple::Pixel)
@@ -1081,6 +1107,12 @@ static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environm
.Case("hull", llvm::Triple::Hull)
.Case("domain", llvm::Triple::Domain)
.Case("compute", llvm::Triple::Compute)
+ .Case("raygeneration", llvm::Triple::RayGeneration)
+ .Case("intersection", llvm::Triple::Intersection)
+ .Case("anyhit", llvm::Triple::AnyHit)
+ .Case("closesthit", llvm::Triple::ClosestHit)
+ .Case("miss", llvm::Triple::Miss)
+ .Case("callable", llvm::Triple::Callable)
.Case("mesh", llvm::Triple::Mesh)
.Case("amplification", llvm::Triple::Amplification)
.Case("library", llvm::Triple::Library)
@@ -4475,6 +4507,26 @@ def HLSLShader : InheritableAttr {
"Miss", "Callable", "Mesh", "Amplification"]>
];
let Documentation = [HLSLSV_ShaderTypeAttrDocs];
+ let AdditionalMembers =
+[{static llvm::Triple::EnvironmentType getTypeAsEnvironment(HLSLShaderAttr::ShaderType ShaderType) {
+ switch (ShaderType) {
+ case HLSLShaderAttr::Pixel: return llvm::Triple::EnvironmentType::Pixel;
+ case HLSLShaderAttr::Vertex: return llvm::Triple::EnvironmentType::Vertex;
+ case HLSLShaderAttr::Geometry: return llvm::Triple::EnvironmentType::Geometry;
+ case HLSLShaderAttr::Hull: return llvm::Triple::EnvironmentType::Hull;
+ case HLSLShaderAttr::Domain: return llvm::Triple::EnvironmentType::Domain;
+ case HLSLShaderAttr::Compute: return llvm::Triple::EnvironmentType::Compute;
+ case HLSLShaderAttr::RayGeneration: return llvm::Triple::EnvironmentType::RayGeneration;
+ case HLSLShaderAttr::Intersection: return llvm::Triple::EnvironmentType::Intersection;
+ case HLSLShaderAttr::AnyHit: return llvm::Triple::EnvironmentType::AnyHit;
+ case HLSLShaderAttr::ClosestHit: return llvm::Triple::EnvironmentType::ClosestHit;
+ case HLSLShaderAttr::Miss: return llvm::Triple::EnvironmentType::Miss;
+ case HLSLShaderAttr::Callable: return llvm::Triple::EnvironmentType::Callable;
+ case HLSLShaderAttr::Mesh: return llvm::Triple::EnvironmentType::Mesh;
+ case HLSLShaderAttr::Amplification: return llvm::Triple::EnvironmentType::Amplification;
+ }
+ }
+}];
}
def HLSLResource : InheritableAttr {
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 4cb4f3d999f7a..f239198b5f090 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1515,6 +1515,9 @@ def HLSLMixPackOffset : DiagGroup<"mix-packoffset">;
// Warnings for DXIL validation
def DXILValidation : DiagGroup<"dxil-validation">;
+// Warning for HLSL API availability
+def HLSLAvailability : DiagGroup<"hlsl-availability">;
+
// Warnings and notes related to const_var_decl_type attribute checks
def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e3b4186f1b06f..287a2cdc263a8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12224,6 +12224,13 @@ def err_hlsl_param_qualifier_mismatch :
def warn_hlsl_impcast_vector_truncation : Warning<
"implicit conversion truncates vector: %0 to %1">, InGroup<Conversion>;
+def warn_hlsl_availability : Warning<
+ "%0 is only available %select{|in %4 environment }3on %1 %2 or newer">,
+ InGroup<HLSLAvailability>, DefaultError;
+def warn_hlsl_availability_unavailable :
+ Warning<err_unavailable.Summary>,
+ InGroup<HLSLAvailability>, DefaultError;
+
// Layout randomization diagnostics.
def err_non_designated_init_used : Error<
"a randomized struct can only be initialized with a designated initializer">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 34acaf19517f2..eac1f7c07c85d 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -49,6 +49,7 @@ class SemaHLSL : public SemaBase {
void DiagnoseAttrStageMismatch(
const Attr *A, HLSLShaderAttr::ShaderType Stage,
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
+ void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
};
} // namespace clang
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index f847c49920cf3..9dfa7b3b3a2a7 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1351,6 +1351,9 @@ void Sema::ActOnEndOfTranslationUnit() {
Consumer.CompleteExternalDeclaration(D);
}
+ if (LangOpts.HLSL)
+ HLSL().DiagnoseAvailabilityViolations(getASTContext().getTranslationUnitDecl());
+
// If there were errors, disable 'unused' warnings since they will mostly be
// noise. Don't warn for a use from a module: either we should warn on all
// file-scope declarations in modules or not at all, but whether the
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 663b6f35b869d..e5cf3037aedef 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -228,8 +229,9 @@ shouldDiagnoseAvailabilityByDefault(const ASTContext &Context,
ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13);
break;
case llvm::Triple::ShaderModel:
- // Always enable availability diagnostics for shader models.
- return true;
+ // FIXME: This will be updated when HLSL strict diagnostic mode
+ // is implemented (issue #90096)
+ return false;
default:
// New targets should always warn about availability.
return Triple.getVendor() == llvm::Triple::Apple;
@@ -438,6 +440,10 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
<< S.Context.getTargetInfo().getPlatformMinVersion().getAsString()
<< UseEnvironment << AttrEnvironment << TargetEnvironment;
+ // Do not offer to silence the warning or fixits for HLSL
+ if (S.getLangOpts().HLSL)
+ return;
+
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
if (TD->getDeclName().isEmpty()) {
@@ -865,6 +871,10 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
<< SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
<< UseEnvironment << AttrEnvironment << TargetEnvironment;
+ // Do not offer to silence the warning or fixits for HLSL
+ if (SemaRef.getLangOpts().HLSL)
+ return;
+
auto FixitDiag =
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
<< Range << D
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 6a12c417e2f3a..286bd1354fd9f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -9,6 +9,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaHLSL.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TargetInfo.h"
@@ -16,6 +19,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TargetParser/Triple.h"
#include <iterator>
@@ -290,3 +294,295 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
<< A << HLSLShaderAttr::ConvertShaderTypeToStr(Stage)
<< (AllowedStages.size() != 1) << join(StageStrings, ", ");
}
+
+namespace {
+
+/// This class implements HLSL availability diagnostics for default
+/// and relaxed mode
+///
+/// The goal of this diagnostic is to emit an error or warning when an
+/// unavailable API is found in a code that is reachable from the shader
+/// entry function or from an exported function (when compiling shader
+/// library).
+///
+/// This is done by traversing the AST of all shader entry point functions
+/// and of all exported functions, and any functions that are refrenced
+/// from this AST. In other words, any function that are reachable from
+/// the entry points.
+class DiagnoseHLSLAvailability
+ : public RecursiveASTVisitor<DiagnoseHLSLAvailability> {
+ // HEKOTAS this is probably not needed
+ // typedef RecursiveASTVisitor<DiagnoseHLSLAvailability> Base;
+
+ Sema &SemaRef;
+
+ // Stack of functions to be scaned
+ llvm::SmallVector<const FunctionDecl *, 8> DeclsToScan;
+
+ // List of functions that were already scanned and in which environment.
+ //
+ // Maps FunctionDecl to a unsigned number that represents a set of shader
+ // environments the function has been scanned for.
+ // Since HLSLShaderAttr::ShaderType enum is generated from Attr.td and is
+ // defined without any assigned values, it is guaranteed to be numbered
+ // sequentially from 0 up and we can use it to 'index' individual bits
+ // in the set.
+ // The N'th bit in the set will be set if the function has been scanned
+ // in shader environment whose ShaderType integer value equals N.
+ // For example, if a function has been scanned in compute and pixel stage
+ // environment, the value will be 0x21 (100001 binary) because
+ // (int)HLSLShaderAttr::ShaderType::Pixel == 1 and
+ // (int)HLSLShaderAttr::ShaderType::Compute == 5.
+ llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
+
+ // Do not access these directly, use the get/set methods below to make
+ // sure the values are in sync
+ llvm::Triple::EnvironmentType CurrentShaderEnvironment;
+ unsigned CurrentShaderStageBit;
+
+ // True if scanning a function that was already scanned in a different
+ // shader stage context, and therefore we should not report issues that
+ // depend only on shader model version because they would be duplicate.
+ bool ReportOnlyShaderStageIssues;
+
+ void SetShaderStageContext(HLSLShaderAttr::ShaderType ShaderType) {
+ assert((((unsigned)1) << (unsigned)ShaderType) != 0 &&
+ "ShaderType is too big for this bitmap");
+ CurrentShaderEnvironment = HLSLShaderAttr::getTypeAsEnvironment(ShaderType);
+ CurrentShaderStageBit = (1 << ShaderType);
+ }
+ void SetUnknownShaderStageContext() {
+ CurrentShaderEnvironment =
+ llvm::Triple::EnvironmentType::UnknownEnvironment;
+ CurrentShaderStageBit = (1 << 31);
+ }
+ llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() {
+ return CurrentShaderEnvironment;
+ }
+ bool InUnknownShaderStageContext() {
+ return CurrentShaderEnvironment ==
+ llvm::Triple::EnvironmentType::UnknownEnvironment;
+ }
+
+ // Scanning methods
+ void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
+ void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
+ SourceRange Range);
+ const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
+ bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
+ bool WasAlreadyScannedInCurrentShaderStage(const FunctionDecl *FD,
+ bool *WasNeverScanned = nullptr);
+ void AddToScannedFunctions(const FunctionDecl *FD);
+
+public:
+ DiagnoseHLSLAvailability(Sema &SemaRef) : SemaRef(SemaRef) {}
+
+ // AST traversal methods
+ void RunOnTranslationUnit(const TranslationUnitDecl *TU);
+ void RunOnFunction(const FunctionDecl *FD);
+
+ bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+ FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());
+ if (FD)
+ HandleFunctionOrMethodRef(FD, DRE);
+ return true;
+ }
+
+ bool VisitMemberExpr(MemberExpr *ME) {
+ FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());
+ if (FD)
+ HandleFunctionOrMethodRef(FD, ME);
+ return true;
+ }
+};
+
+// Returns true if the function has already been scanned in the current
+// shader environment. WasNeverScanned will be set to true if the function
+// has never been scanned before for any shader environment.
+bool DiagnoseHLSLAvailability::WasAlreadyScannedInCurrentShaderStage(
+ const FunctionDecl *FD, bool *WasNeverScanned) {
+ const unsigned &ScannedStages = ScannedDecls.getOrInsertDefault(FD);
+ if (WasNeverScanned)
+ *WasNeverScanned = (ScannedStages == 0);
+ return ScannedStages & CurrentShaderStageBit;
+}
+
+// Marks the function as scanned in the current shader environment
+void DiagnoseHLSLAvailability::AddToScannedFunctions(const FunctionDecl *FD) {
+ unsigned &ScannedStages = ScannedDecls.getOrInsertDefault(FD);
+ ScannedStages |= CurrentShaderStageBit;
+}
+
+void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
+ Expr *RefExpr) {
+ assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
+ "expected DeclRefExpr or MemberExpr");
+
+ // has a definition -> add to stack to be scanned
+ const FunctionDecl *FDWithBody = nullptr;
+ if (FD->hasBody(FDWithBody)) {
+ if (!WasAlreadyScannedInCurrentShaderStage(FDWithBody))
+ DeclsToScan.push_back(FDWithBody);
+ return;
+ }
+
+ // no body -> diagnose availability
+ const AvailabilityAttr *AA = FindAvailabilityAttr(FD);
+ if (AA)
+ CheckDeclAvailability(
+ FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));
+}
+
+void DiagnoseHLSLAvailability::RunOnTranslationUnit(
+ const TranslationUnitDecl *TU) {
+ // Iterate over all shader entry functions and library exports, and for those
+ // that have a body (definiton), run diag scan on each, setting appropriate
+ // shader environment context based on whether it is a shader entry function
+ // or an exported function.
+ for (auto &D : TU->decls()) {
+ const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);
+ if (!FD || !FD->isThisDeclarationADefinition())
+ continue;
+
+ // shader entry point
+ auto ShaderAttr = FD->getAttr<HLSLShaderAttr>();
+ if (ShaderAttr) {
+ SetShaderStageContext(ShaderAttr->getType());
+ RunOnFunction(FD);
+ continue;
+ }
+ // exported library function with definition
+ // FIXME: tracking issue #92073
+#if 0
+ if (FD->getFormalLinkage() == Linkage::External) {
+ SetUnknownShaderStageContext();
+ RunOnFunction(FD);
+ }
+#endif
+ }
+}
+
+void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
+ assert(DeclsToScan.empty() && "DeclsToScan should be empty");
+ DeclsToScan.push_back(FD);
+
+ while (!DeclsToScan.empty()) {
+ // Take one decl from the stack and check it by traversing its AST.
+ // For any CallExpr found during the traversal add it's callee to the top of
+ // the stack to be processed next. Functions already processed are stored in
+ // ScannedDecls.
+ const FunctionDecl *FD = DeclsToScan.back();
+ DeclsToScan.pop_back();
+
+ // Decl was already scanned
+ bool WasNeverScanned;
+ if (WasAlreadyScannedInCurrentShaderStage(FD, &WasNeverScanned))
+ continue;
+
+ ReportOnlyShaderStageIssues = !WasNeverScanned;
+
+ AddToScannedFunctions(FD);
+
+ Stmt *Body = FD->getBody();
+ assert(Body && "full definition with body expected here");
+
+ TraverseStmt(Body);
+ }
+}
+
+bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(
+ const AvailabilityAttr *AA) {
+ IdentifierInfo *IIEnvironment = AA->getEnvironment();
+ if (!IIEnvironment)
+ return true;
+
+ llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();
+ if (CurrentEnv == llvm::Triple::UnknownEnvironment)
+ return false;
+
+ llvm::Triple::EnvironmentType AttrEnv =
+ AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
+
+ return CurrentEnv == AttrEnv;
+}
+
+const AvailabilityAttr *
+DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {
+ AvailabilityAttr const *PartialMatch = nullptr;
+ // Check each AvailabilityAttr to find the one for this platform.
+ // For multiple attributes with the same platform try to find one for this
+ // environment.
+ for (const auto *A : D->attrs()) {
+ if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
+ StringRef AttrPlatform = Avail->getPlatform()->getName();
+ StringRef TargetPlatform =
+ SemaRef.getASTContext().getTargetInfo().getPlatformName();
+
+ // Match the platform name.
+ if (AttrPlatform == TargetPlatform) {
+ // Find the best matching attribute for this environment
+ if (HasMatchingEnvironmentOrNone(Avail))
+ return Avail;
+ PartialMatch = Avail;
+ }
+ }
+ }
+ return PartialMatch;
+}
+
+// Check availability against target shader model version and current shader
+// stage and emit diagnostic
+void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
+ const AvailabilityAttr *AA,
+ SourceRange Range) {
+ if (ReportOnlyShaderStageIssues && !AA->getEnvironment())
+ return;
+
+ bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);
+ VersionTuple Introduced = AA->getIntroduced();
+ VersionTuple TargetVersion =
+ SemaRef.Context.getTargetInfo().getPlatformMinVersion();
+
+ if (TargetVersion >= Introduced && EnvironmentMatches)
+ return;
+
+ // Do not diagnose shade-stage-specific availability when the shader stage
+ // context is unknown
+ if (InUnknownShaderStageContext() && AA->getEnvironment() != nullptr) {
+ return;
+ }
+
+ // Emit diagnostic message
+ const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
+ llvm::StringRef PlatformName(
+ AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
+
+ llvm::StringRef CurrentEnvStr = AvailabilityAttr::getPrettyEnviromentName(
+ AvailabilityAttr::getEnvironmentString(GetCurrentShaderEnvironment()));
+
+ llvm::StringRef AttrEnvStr = AA->getEnvironment()
+ ? AvailabilityAttr::getPrettyEnviromentName(
+ AA->getEnvironment()->getName())
+ : "";
+ bool UseEnvironment = !AttrEnvStr.empty();
+
+ if (EnvironmentMatches) {
+ SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)
+ << Range << D << PlatformName << Introduced.getAsString()
+ << UseEnvironment << CurrentEnvStr;
+ } else {
+ SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)
+ << Range << D;
+ }
+
+ SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)
+ << D << PlatformName << Introduced.getAsString()
+ << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
+ << UseEnvironment << AttrEnvStr << CurrentEnvStr;
+}
+
+} // namespace
+
+void SemaHLSL::DiagnoseAvailabilityViolations(TranslationUnitDecl *TU) {
+ DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);
+}
diff --git a/clang/test/Sema/attr-availability-shadermodel-compute.hlsl b/clang/test/Sema/attr-availability-shadermodel-compute.hlsl
new file mode 100644
index 0000000000000..dd02148088af5
--- /dev/null
+++ b/clang/test/Sema/attr-availability-shadermodel-compute.hlsl
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-compute -fsyntax-only -verify %s
+
+// Platform shader model, no environment parameter
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned f1(); // #f1
+
+__attribute__((availability(shadermodel, introduced = 5.1)))
+unsigned f2(); // #f2
+
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned f3();
+
+// Platform shader model, environment parameter restricting earlier version,
+// available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned f4(); // #f4
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned f5();
+
+// Platform shader model, environment parameter restricting earlier version,
+// never available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
+unsigned f6(); // #f6
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned f7(); // #f7
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned f8();
+
+[numthreads(4,1,1)]
+int main() {
+ // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ unsigned A = f1(); // #f1_call
+
+ // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
+ // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
+ unsigned B = f2(); // #f2_call
+
+ unsigned C = f3();
+
+ // expected-error@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ unsigned D = f4(); // #f4_call
+
+ unsigned E = f5();
+
+ // expected-error@#f6_call {{'f6' is only available in compute shader environment on Shader Model 6.0 or newer}}
+ // expected-note@#f6 {{'f6' has been marked as being introduced in Shader Model 6.0 in compute shader environment here, but the deployment target is Shader Model 5.0}}
+ unsigned F = f6(); // #f6_call
+
+ // expected-error@#f7_call {{'f7' is unavailable}}
+ // expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 compute shader environment}}
+ unsigned G = f7(); // #f7_call
+
+ unsigned H = f8();
+
+ return 0;
+}
diff --git a/clang/test/Sema/attr-availability-shadermodel-mesh.hlsl b/clang/test/Sema/attr-availability-shadermodel-mesh.hlsl
new file mode 100644
index 0000000000000..256f0a2837c60
--- /dev/null
+++ b/clang/test/Sema/attr-availability-shadermodel-mesh.hlsl
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-mesh -fsyntax-only -verify %s
+
+// Platform shader model, no environment parameter
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned f1(); // #f1
+
+__attribute__((availability(shadermodel, introduced = 5.1)))
+unsigned f2(); // #f2
+
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned f3();
+
+// Platform shader model, environment parameter restricting earlier version,
+// available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned f4(); // #f4
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned f5(); // #f5
+
+// Platform shader model, environment parameter restricting earlier version,
+// never available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
+unsigned f6(); // #f6
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned f7(); // #f7
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned f8(); // #f8
+
+[numthreads(4,1,1)]
+int main() {
+ // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ unsigned A = f1(); // #f1_call
+
+ // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
+ // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
+ unsigned B = f2(); // #f2_call
+
+ unsigned C = f3();
+
+ // expected-error@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ unsigned D = f4(); // #f4_call
+
+ unsigned E = f5(); // #f5_call
+
+ unsigned F = f6(); // #f6_call
+
+ // expected-error@#f7_call {{'f7' is only available in mesh shader environment on Shader Model 6.0 or newer}}
+ // expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}}
+ unsigned G = f7(); // #f7_call
+
+ // expected-error@#f8_call {{'f8' is only available in mesh shader environment on Shader Model 6.0 or newer}}
+ // expected-note@#f8 {{'f8' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}}
+ unsigned H = f8(); // #f8_call
+
+ return 0;
+}
diff --git a/clang/test/Sema/attr-availability-shadermodel-pixel.hlsl b/clang/test/Sema/attr-availability-shadermodel-pixel.hlsl
new file mode 100644
index 0000000000000..7cd13e653ed5a
--- /dev/null
+++ b/clang/test/Sema/attr-availability-shadermodel-pixel.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-pixel -fsyntax-only -verify %s
+
+// Platform shader model, no environment parameter
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned f1(); // #f1
+
+__attribute__((availability(shadermodel, introduced = 5.1)))
+unsigned f2(); // #f2
+
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned f3();
+
+// Platform shader model, environment parameter restricting earlier version,
+// available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned f4(); // #f4
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned f5();
+
+// Platform shader model, environment parameter restricting earlier version,
+// never available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
+unsigned f6(); // #f6
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned f7(); // #f7
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned f8();
+
+int main() {
+ // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ unsigned A = f1(); // #f1_call
+
+ // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
+ // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
+ unsigned B = f2(); // #f2_call
+
+ unsigned C = f3();
+
+ unsigned D = f4(); // #f4_call
+
+ unsigned E = f5();
+
+ unsigned F = f6(); // #f6_call
+
+ unsigned G = f7(); // #f7_call
+
+ unsigned H = f8();
+
+ return 0;
+}
diff --git a/clang/test/Sema/attr-availability-shadermodel.hlsl b/clang/test/Sema/attr-availability-shadermodel.hlsl
new file mode 100644
index 0000000000000..2682eb5fbb5c2
--- /dev/null
+++ b/clang/test/Sema/attr-availability-shadermodel.hlsl
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.5-library -fsyntax-only -verify %s
+
+
+void f1(void) __attribute__((availability(shadermodel, introduced = 6.0, environment="pixel"))); // expected-error {{expected an environment name, e.g., 'compute'}}
+
+void f2(void) __attribute__((availability(shadermodel, introduced = 6.0, environment=pixel, environment=compute))); // expected-error {{redundant 'environment' availability change; only the last specified change will be used}}
+
+void f3(void) __attribute__((availability(shadermodel, strict, introduced = 6.0, environment = mesh))); // expected-error {{unexpected parameter 'strict' in availability attribute, not permitted in HLSL}}
+
+int main() {
+}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
new file mode 100644
index 0000000000000..80a40adede0dd
--- /dev/null
+++ b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
+// RUN: -fsyntax-only -verify %s
+
+__attribute__((availability(shadermodel, introduced = 6.5)))
+float fx(float); // #fx
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
+float fy(float); // #fy
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
+float fz(float); // #fz
+
+float also_alive(float f) {
+ // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #also_alive_fx_call
+ // expected-error@#also_alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #also_alive_fy_call
+ // expected-error@#also_alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #also_alive_fz_call
+ return 0;
+}
+
+float alive(float f) {
+ // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #alive_fx_call
+ // expected-error@#alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #alive_fy_call
+ // expected-error@#alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #alive_fz_call
+
+ return also_alive(f);
+}
+
+float also_dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+ return 0;
+}
+
+float dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+
+ return also_dead(f);
+}
+
+template<typename T>
+T aliveTemp(T f) {
+ // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #aliveTemp_fx_call
+ // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #aliveTemp_fy_call
+ // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #aliveTemp_fz_call
+ return 0;
+}
+
+class MyClass
+{
+ float F;
+ float makeF() {
+ // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(F); // #MyClass_makeF_fx_call
+ // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(F); // #MyClass_makeF_fy_call
+ // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(F); // #MyClass_makeF_fz_call
+ return 0;
+ }
+};
+
+[numthreads(4,1,1)]
+float main() {
+ float f = 3;
+ MyClass C = { 1.0f };
+ float a = alive(f);
+ float b = aliveTemp<float>(f); // #aliveTemp_inst
+ float c = C.makeF();
+ return a * b * c;
+}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
new file mode 100644
index 0000000000000..7290bdb6ce029
--- /dev/null
+++ b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
+// RUN: -fsyntax-only -verify %s
+
+__attribute__((availability(shadermodel, introduced = 6.5)))
+float fx(float); // #fx
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
+float fy(float); // #fy
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
+float fz(float); // #fz
+
+float also_alive(float f) {
+ // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #also_alive_fx_call
+
+ // expected-error@#also_alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #also_alive_fy_call
+
+ // expected-error@#also_alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #also_alive_fz_call
+
+ return 0;
+}
+
+float alive(float f) {
+ // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #alive_fx_call
+
+ // expected-error@#alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #alive_fy_call
+
+ // expected-error@#alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #alive_fz_call
+
+ return also_alive(f);
+}
+
+float also_dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+ return 0;
+}
+
+float dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+ return also_dead(f);
+}
+
+template<typename T>
+T aliveTemp(T f) {
+ // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #aliveTemp_fx_call
+ // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #aliveTemp_fy_call
+ // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #aliveTemp_fz_call
+ return 0;
+}
+
+class MyClass
+{
+ float F;
+ float makeF() {
+ // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(F); // #MyClass_makeF_fx_call
+ // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(F); // #MyClass_makeF_fy_call
+ // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(F); // #MyClass_makeF_fz_call
+ return 0;
+ }
+};
+
+// Shader entry point without body
+[shader("compute")]
+[numthreads(4,1,1)]
+float main();
+
+// Shader entry point with body
+[shader("compute")]
+[numthreads(4,1,1)]
+float main() {
+ float f = 3;
+ MyClass C = { 1.0f };
+ float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
+ float c = C.makeF();
+ return a * b * c;
+}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
new file mode 100644
index 0000000000000..dfb0000db99cd
--- /dev/null
+++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
+// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s
+
+__attribute__((availability(shadermodel, introduced = 6.5)))
+float fx(float); // #fx
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
+float fy(float); // #fy
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
+float fz(float); // #fz
+
+float also_alive(float f) {
+ // expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #also_alive_fx_call
+ // expected-warning@#also_alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #also_alive_fy_call
+ // expected-warning@#also_alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #also_alive_fz_call
+ return 0;
+}
+
+float alive(float f) {
+ // expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #alive_fx_call
+ // expected-warning@#alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #alive_fy_call
+ // expected-warning@#alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #alive_fz_call
+
+ return also_alive(f);
+}
+
+float also_dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+ return 0;
+}
+
+float dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+
+ return also_dead(f);
+}
+
+template<typename T>
+T aliveTemp(T f) {
+ // expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #aliveTemp_fx_call
+ // expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #aliveTemp_fy_call
+ // expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #aliveTemp_fz_call
+ return 0;
+}
+
+class MyClass
+{
+ float F;
+ float makeF() {
+ // expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(F); // #MyClass_makeF_fx_call
+ // expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(F); // #MyClass_makeF_fy_call
+ // expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(F); // #MyClass_makeF_fz_call
+ return 0;
+ }
+};
+
+[numthreads(4,1,1)]
+float main() {
+ float f = 3;
+ MyClass C = { 1.0f };
+ float a = alive(f);
+ float b = aliveTemp<float>(f); // #aliveTemp_inst
+ float c = C.makeF();
+ return a * b * c;
+}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
new file mode 100644
index 0000000000000..4d6e06faef8ac
--- /dev/null
+++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
+// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s
+
+__attribute__((availability(shadermodel, introduced = 6.5)))
+float fx(float); // #fx
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
+float fy(float); // #fy
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
+float fz(float); // #fz
+
+float also_alive(float f) {
+ // expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #also_alive_fx_call
+
+ // expected-warning@#also_alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #also_alive_fy_call
+
+ // expected-warning@#also_alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #also_alive_fz_call
+
+ return 0;
+}
+
+float alive(float f) {
+ // expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #alive_fx_call
+
+ // expected-warning@#alive_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #alive_fy_call
+
+ // expected-warning@#alive_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #alive_fz_call
+
+ return also_alive(f);
+}
+
+float also_dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+ return 0;
+}
+
+float dead(float f) {
+ // unreachable code - no errors expected
+ float A = fx(f);
+ float B = fy(f);
+ float C = fz(f);
+ return also_dead(f);
+}
+
+template<typename T>
+T aliveTemp(T f) {
+ // expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #aliveTemp_fx_call
+ // expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #aliveTemp_fy_call
+ // expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(f); // #aliveTemp_fz_call
+ return 0;
+}
+
+class MyClass
+{
+ float F;
+ float makeF() {
+ // expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(F); // #MyClass_makeF_fx_call
+ // expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(F); // #MyClass_makeF_fy_call
+ // expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float C = fz(F); // #MyClass_makeF_fz_call
+ return 0;
+ }
+};
+
+// Shader entry point without body
+[shader("compute")]
+[numthreads(4,1,1)]
+float main();
+
+// Shader entry point with body
+[shader("compute")]
+[numthreads(4,1,1)]
+float main() {
+ float f = 3;
+ MyClass C = { 1.0f };
+ float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
+ float c = C.makeF();
+ return a * b * c;
+}
diff --git a/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl b/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl
new file mode 100644
index 0000000000000..ae096ebe8be23
--- /dev/null
+++ b/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
+// RUN: -fsyntax-only -verify %s
+
+__attribute__((availability(shadermodel, introduced = 6.5)))
+float fx(float); // #fx
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
+float fy(float); // #fy
+
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+float fz(float); // #fz
+
+
+void F(float f) {
+ // Make sure we only get this error once, even though this function is scanned twice - once
+ // in compute shader context and once in pixel shader context.
+ // expected-error@#fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ float A = fx(f); // #fx_call
+
+ // expected-error@#fy_call {{'fy' is only available in compute shader environment on Shader Model 6.5 or newer}}
+ // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute shader environment here, but the deployment target is Shader Model 6.0 compute shader environment}}
+ float B = fy(f); // #fy_call
+
+ // expected-error@#fz_call {{'fz' is unavailable}}
+ // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 5.0 in compute shader environment here, but the deployment target is Shader Model 6.0 pixel shader environment}}
+ float X = fz(f); // #fz_call
+}
+
+void deadCode(float f) {
+ // no diagnostics expected under default diagnostic mode
+ float A = fx(f);
+ float B = fy(f);
+ float X = fz(f);
+}
+
+// Pixel shader
+[shader("pixel")]
+void mainPixel() {
+ F(1.0);
+}
+
+// First Compute shader
+[shader("compute")]
+[numthreads(4,1,1)]
+void mainCompute1() {
+ F(2.0);
+}
+
+// Second compute shader to make sure we do not get duplicate messages if F is called
+// from multiple entry points.
+[shader("compute")]
+[numthreads(4,1,1)]
+void mainCompute2() {
+ F(3.0);
+}
diff --git a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
index 185b79be37be5..6333c63569327 100644
--- a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
+++ b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
@@ -1,9 +1,10 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel5.0-library -verify %s
// WaveActiveCountBits is unavailable before ShaderModel 6.0.
-unsigned foo(bool b) {
- // expected-warning@#site {{'WaveActiveCountBits' is only available on Shader Model 6.0 or newer}}
+[shader("compute")]
+[numthreads(8,8,1)]
+unsigned foo() {
+ // expected-error@#site {{'WaveActiveCountBits' is only available on Shader Model 6.0 or newer}}
// expected-note at hlsl/hlsl_intrinsics.h:* {{'WaveActiveCountBits' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#site {{enclose 'WaveActiveCountBits' in a __builtin_available check to silence this warning}}
- return hlsl::WaveActiveCountBits(b); // #site
+ return hlsl::WaveActiveCountBits(1); // #site
}
>From 74817635c3c7d813b490211b7c2c70a8e2eff3a4 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Sun, 19 May 2024 11:27:18 -0700
Subject: [PATCH 2/9] clang-format
---
clang/lib/Sema/Sema.cpp | 3 ++-
clang/lib/Sema/SemaHLSL.cpp | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 9dfa7b3b3a2a7..8ee40d3e0d0e4 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1352,7 +1352,8 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (LangOpts.HLSL)
- HLSL().DiagnoseAvailabilityViolations(getASTContext().getTranslationUnitDecl());
+ HLSL().DiagnoseAvailabilityViolations(
+ getASTContext().getTranslationUnitDecl());
// If there were errors, disable 'unused' warnings since they will mostly be
// noise. Don't warn for a use from a module: either we should warn on all
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 286bd1354fd9f..6e407cfc4e375 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -341,7 +341,7 @@ class DiagnoseHLSLAvailability
unsigned CurrentShaderStageBit;
// True if scanning a function that was already scanned in a different
- // shader stage context, and therefore we should not report issues that
+ // shader stage context, and therefore we should not report issues that
// depend only on shader model version because they would be duplicate.
bool ReportOnlyShaderStageIssues;
>From 6fc46289d7cea043eaeeb3bb465389eb1840d0ca Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Sun, 19 May 2024 13:12:09 -0700
Subject: [PATCH 3/9] Update tests - the warning is now error and no fix-it
note for HLSL
---
.../Availability/attr-availability-compute.hlsl | 15 +++++----------
.../Availability/attr-availability-mesh.hlsl | 15 +++++----------
.../Availability/attr-availability-pixel.hlsl | 6 ++----
3 files changed, 12 insertions(+), 24 deletions(-)
diff --git a/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
index 8fa696ea11649..dd02148088af5 100644
--- a/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
@@ -38,33 +38,28 @@ unsigned f8();
[numthreads(4,1,1)]
int main() {
- // expected-warning@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
+ // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
// expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f1_call {{enclose 'f1' in a __builtin_available check to silence this warning}}
unsigned A = f1(); // #f1_call
- // expected-warning@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
+ // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
// expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f2_call {{enclose 'f2' in a __builtin_available check to silence this warning}}
unsigned B = f2(); // #f2_call
unsigned C = f3();
- // expected-warning@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
+ // expected-error@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
// expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f4_call {{enclose 'f4' in a __builtin_available check to silence this warning}}
unsigned D = f4(); // #f4_call
unsigned E = f5();
- // expected-warning@#f6_call {{'f6' is only available in compute shader environment on Shader Model 6.0 or newer}}
+ // expected-error@#f6_call {{'f6' is only available in compute shader environment on Shader Model 6.0 or newer}}
// expected-note@#f6 {{'f6' has been marked as being introduced in Shader Model 6.0 in compute shader environment here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f6_call {{enclose 'f6' in a __builtin_available check to silence this warning}}
unsigned F = f6(); // #f6_call
- // expected-warning@#f7_call {{'f7' is unavailable}}
+ // expected-error@#f7_call {{'f7' is unavailable}}
// expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 compute shader environment}}
- // expected-note@#f7_call {{enclose 'f7' in a __builtin_available check to silence this warning}}
unsigned G = f7(); // #f7_call
unsigned H = f8();
diff --git a/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
index 40a7ddbb1de98..256f0a2837c60 100644
--- a/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
+++ b/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
@@ -38,35 +38,30 @@ unsigned f8(); // #f8
[numthreads(4,1,1)]
int main() {
- // expected-warning@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
+ // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
// expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f1_call {{enclose 'f1' in a __builtin_available check to silence this warning}}
unsigned A = f1(); // #f1_call
- // expected-warning@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
+ // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
// expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f2_call {{enclose 'f2' in a __builtin_available check to silence this warning}}
unsigned B = f2(); // #f2_call
unsigned C = f3();
- // expected-warning@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
+ // expected-error@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
// expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f4_call {{enclose 'f4' in a __builtin_available check to silence this warning}}
unsigned D = f4(); // #f4_call
unsigned E = f5(); // #f5_call
unsigned F = f6(); // #f6_call
- // expected-warning@#f7_call {{'f7' is only available in mesh shader environment on Shader Model 6.0 or newer}}
+ // expected-error@#f7_call {{'f7' is only available in mesh shader environment on Shader Model 6.0 or newer}}
// expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}}
- // expected-note@#f7_call {{enclose 'f7' in a __builtin_available check to silence this warning}}
unsigned G = f7(); // #f7_call
- // expected-warning@#f8_call {{'f8' is only available in mesh shader environment on Shader Model 6.0 or newer}}
+ // expected-error@#f8_call {{'f8' is only available in mesh shader environment on Shader Model 6.0 or newer}}
// expected-note@#f8 {{'f8' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}}
- // expected-note@#f8_call {{enclose 'f8' in a __builtin_available check to silence this warning}}
unsigned H = f8(); // #f8_call
return 0;
diff --git a/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
index 59d09a9cd276f..7cd13e653ed5a 100644
--- a/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
+++ b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
@@ -37,14 +37,12 @@ __attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
unsigned f8();
int main() {
- // expected-warning@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
+ // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
// expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f1_call {{enclose 'f1' in a __builtin_available check to silence this warning}}
unsigned A = f1(); // #f1_call
- // expected-warning@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
+ // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
// expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#f2_call {{enclose 'f2' in a __builtin_available check to silence this warning}}
unsigned B = f2(); // #f2_call
unsigned C = f3();
>From 1bb5efe7ffd5cdcd27e9976be7c1d0afdc03ec7b Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Mon, 20 May 2024 07:52:30 -0700
Subject: [PATCH 4/9] Remove whitespace
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 287a2cdc263a8..874e7ff187ee2 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12230,7 +12230,7 @@ def warn_hlsl_availability : Warning<
def warn_hlsl_availability_unavailable :
Warning<err_unavailable.Summary>,
InGroup<HLSLAvailability>, DefaultError;
-
+
// Layout randomization diagnostics.
def err_non_designated_init_used : Error<
"a randomized struct can only be initialized with a designated initializer">;
>From ccf71cfcca316418a2d83fb3ef7eaf1d40766606 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Mon, 20 May 2024 08:12:24 -0700
Subject: [PATCH 5/9] These tests were moved to SemaHLSL in previous PR and
renamed in this one.
---
...attr-availability-shadermodel-compute.hlsl | 68 -------------------
.../attr-availability-shadermodel-mesh.hlsl | 68 -------------------
.../attr-availability-shadermodel-pixel.hlsl | 61 -----------------
.../Sema/attr-availability-shadermodel.hlsl | 11 ---
4 files changed, 208 deletions(-)
delete mode 100644 clang/test/Sema/attr-availability-shadermodel-compute.hlsl
delete mode 100644 clang/test/Sema/attr-availability-shadermodel-mesh.hlsl
delete mode 100644 clang/test/Sema/attr-availability-shadermodel-pixel.hlsl
delete mode 100644 clang/test/Sema/attr-availability-shadermodel.hlsl
diff --git a/clang/test/Sema/attr-availability-shadermodel-compute.hlsl b/clang/test/Sema/attr-availability-shadermodel-compute.hlsl
deleted file mode 100644
index dd02148088af5..0000000000000
--- a/clang/test/Sema/attr-availability-shadermodel-compute.hlsl
+++ /dev/null
@@ -1,68 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-compute -fsyntax-only -verify %s
-
-// Platform shader model, no environment parameter
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned f1(); // #f1
-
-__attribute__((availability(shadermodel, introduced = 5.1)))
-unsigned f2(); // #f2
-
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned f3();
-
-// Platform shader model, environment parameter restricting earlier version,
-// available in all environments in higher versions
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned f4(); // #f4
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned f5();
-
-// Platform shader model, environment parameter restricting earlier version,
-// never available in all environments in higher versions
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
-unsigned f6(); // #f6
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned f7(); // #f7
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned f8();
-
-[numthreads(4,1,1)]
-int main() {
- // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
- // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- unsigned A = f1(); // #f1_call
-
- // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
- // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- unsigned B = f2(); // #f2_call
-
- unsigned C = f3();
-
- // expected-error@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
- // expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- unsigned D = f4(); // #f4_call
-
- unsigned E = f5();
-
- // expected-error@#f6_call {{'f6' is only available in compute shader environment on Shader Model 6.0 or newer}}
- // expected-note@#f6 {{'f6' has been marked as being introduced in Shader Model 6.0 in compute shader environment here, but the deployment target is Shader Model 5.0}}
- unsigned F = f6(); // #f6_call
-
- // expected-error@#f7_call {{'f7' is unavailable}}
- // expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 compute shader environment}}
- unsigned G = f7(); // #f7_call
-
- unsigned H = f8();
-
- return 0;
-}
diff --git a/clang/test/Sema/attr-availability-shadermodel-mesh.hlsl b/clang/test/Sema/attr-availability-shadermodel-mesh.hlsl
deleted file mode 100644
index 256f0a2837c60..0000000000000
--- a/clang/test/Sema/attr-availability-shadermodel-mesh.hlsl
+++ /dev/null
@@ -1,68 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-mesh -fsyntax-only -verify %s
-
-// Platform shader model, no environment parameter
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned f1(); // #f1
-
-__attribute__((availability(shadermodel, introduced = 5.1)))
-unsigned f2(); // #f2
-
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned f3();
-
-// Platform shader model, environment parameter restricting earlier version,
-// available in all environments in higher versions
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned f4(); // #f4
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned f5(); // #f5
-
-// Platform shader model, environment parameter restricting earlier version,
-// never available in all environments in higher versions
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
-unsigned f6(); // #f6
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned f7(); // #f7
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned f8(); // #f8
-
-[numthreads(4,1,1)]
-int main() {
- // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
- // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- unsigned A = f1(); // #f1_call
-
- // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
- // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- unsigned B = f2(); // #f2_call
-
- unsigned C = f3();
-
- // expected-error@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}}
- // expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- unsigned D = f4(); // #f4_call
-
- unsigned E = f5(); // #f5_call
-
- unsigned F = f6(); // #f6_call
-
- // expected-error@#f7_call {{'f7' is only available in mesh shader environment on Shader Model 6.0 or newer}}
- // expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}}
- unsigned G = f7(); // #f7_call
-
- // expected-error@#f8_call {{'f8' is only available in mesh shader environment on Shader Model 6.0 or newer}}
- // expected-note@#f8 {{'f8' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}}
- unsigned H = f8(); // #f8_call
-
- return 0;
-}
diff --git a/clang/test/Sema/attr-availability-shadermodel-pixel.hlsl b/clang/test/Sema/attr-availability-shadermodel-pixel.hlsl
deleted file mode 100644
index 7cd13e653ed5a..0000000000000
--- a/clang/test/Sema/attr-availability-shadermodel-pixel.hlsl
+++ /dev/null
@@ -1,61 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-pixel -fsyntax-only -verify %s
-
-// Platform shader model, no environment parameter
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned f1(); // #f1
-
-__attribute__((availability(shadermodel, introduced = 5.1)))
-unsigned f2(); // #f2
-
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned f3();
-
-// Platform shader model, environment parameter restricting earlier version,
-// available in all environments in higher versions
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned f4(); // #f4
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned f5();
-
-// Platform shader model, environment parameter restricting earlier version,
-// never available in all environments in higher versions
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
-unsigned f6(); // #f6
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned f7(); // #f7
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned f8();
-
-int main() {
- // expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
- // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- unsigned A = f1(); // #f1_call
-
- // expected-error@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}}
- // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- unsigned B = f2(); // #f2_call
-
- unsigned C = f3();
-
- unsigned D = f4(); // #f4_call
-
- unsigned E = f5();
-
- unsigned F = f6(); // #f6_call
-
- unsigned G = f7(); // #f7_call
-
- unsigned H = f8();
-
- return 0;
-}
diff --git a/clang/test/Sema/attr-availability-shadermodel.hlsl b/clang/test/Sema/attr-availability-shadermodel.hlsl
deleted file mode 100644
index 2682eb5fbb5c2..0000000000000
--- a/clang/test/Sema/attr-availability-shadermodel.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.5-library -fsyntax-only -verify %s
-
-
-void f1(void) __attribute__((availability(shadermodel, introduced = 6.0, environment="pixel"))); // expected-error {{expected an environment name, e.g., 'compute'}}
-
-void f2(void) __attribute__((availability(shadermodel, introduced = 6.0, environment=pixel, environment=compute))); // expected-error {{redundant 'environment' availability change; only the last specified change will be used}}
-
-void f3(void) __attribute__((availability(shadermodel, strict, introduced = 6.0, environment = mesh))); // expected-error {{unexpected parameter 'strict' in availability attribute, not permitted in HLSL}}
-
-int main() {
-}
>From 69d3f35923846585e1f725c9d5f16d40127e63cf Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 23 May 2024 13:20:04 -0700
Subject: [PATCH 6/9] Code review feedback
---
clang/include/clang/Basic/Attr.td | 51 +++++++-------------
clang/lib/AST/DeclBase.cpp | 3 +-
clang/lib/Sema/SemaAvailability.cpp | 10 ++--
clang/lib/Sema/SemaHLSL.cpp | 72 ++++++++++++++---------------
4 files changed, 60 insertions(+), 76 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index e5c23d54ab826..d12d3b3b45f52 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1060,42 +1060,23 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
.Case("ShaderModel", "shadermodel")
.Default(Platform);
}
-static llvm::StringRef getPrettyEnviromentName(llvm::StringRef Environment) {
- return llvm::StringSwitch<llvm::StringRef>(Environment)
- .Case("pixel", "pixel shader")
- .Case("vertex", "vertex shader")
- .Case("geometry", "geometry shader")
- .Case("hull", "hull shader")
- .Case("domain", "domain shader")
- .Case("compute", "compute shader")
- .Case("raygeneration", "ray generation shader")
- .Case("intersection", "intersection shader")
- .Case("anyhit", "anyhit shader")
- .Case("closesthit", "closesthit shader")
- .Case("miss", "miss shader")
- .Case("callable", "callable shader")
- .Case("mesh", "mesh shader")
- .Case("amplification", "amplification shader")
- .Case("library", "shader library")
- .Default(Environment);
-}
-static llvm::StringRef getEnvironmentString(llvm::Triple::EnvironmentType EnvironmentType) {
+static llvm::StringRef getPrettyEnviromentName(llvm::Triple::EnvironmentType EnvironmentType) {
switch (EnvironmentType) {
- case llvm::Triple::EnvironmentType::Pixel: return "pixel";
- case llvm::Triple::EnvironmentType::Vertex: return "vertex";
- case llvm::Triple::EnvironmentType::Geometry: return "geometry";
- case llvm::Triple::EnvironmentType::Hull: return "hull";
- case llvm::Triple::EnvironmentType::Domain: return "domain";
- case llvm::Triple::EnvironmentType::Compute: return "compute";
- case llvm::Triple::EnvironmentType::RayGeneration: return "ray generation";
- case llvm::Triple::EnvironmentType::Intersection: return "intersection";
- case llvm::Triple::EnvironmentType::AnyHit: return "any hit";
- case llvm::Triple::EnvironmentType::ClosestHit: return "closest hit";
- case llvm::Triple::EnvironmentType::Miss: return "miss";
- case llvm::Triple::EnvironmentType::Callable: return "callable";
- case llvm::Triple::EnvironmentType::Mesh: return "mesh";
- case llvm::Triple::EnvironmentType::Amplification: return "amplification";
- case llvm::Triple::EnvironmentType::Library: return "library";
+ case llvm::Triple::EnvironmentType::Pixel: return "pixel shader";
+ case llvm::Triple::EnvironmentType::Vertex: return "vertex shader";
+ case llvm::Triple::EnvironmentType::Geometry: return "geometry shader";
+ case llvm::Triple::EnvironmentType::Hull: return "hull shader";
+ case llvm::Triple::EnvironmentType::Domain: return "domain shader";
+ case llvm::Triple::EnvironmentType::Compute: return "compute shader";
+ case llvm::Triple::EnvironmentType::RayGeneration: return "raygeneration shader";
+ case llvm::Triple::EnvironmentType::Intersection: return "intersection shader";
+ case llvm::Triple::EnvironmentType::AnyHit: return "anyhit shader";
+ case llvm::Triple::EnvironmentType::ClosestHit: return "closesthit shader";
+ case llvm::Triple::EnvironmentType::Miss: return "miss shader";
+ case llvm::Triple::EnvironmentType::Callable: return "callable shader";
+ case llvm::Triple::EnvironmentType::Mesh: return "mesh shader";
+ case llvm::Triple::EnvironmentType::Amplification: return "amplification shader";
+ case llvm::Triple::EnvironmentType::Library: return "shader library";
default: return "";
}
}
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 65d5eeb6354eb..ffb22194bce52 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -669,7 +669,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
IdentifierInfo *IIEnv = A->getEnvironment();
StringRef TargetEnv =
Context.getTargetInfo().getTriple().getEnvironmentName();
- StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv);
+ StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(
+ Context.getTargetInfo().getTriple().getEnvironment());
// Matching environment or no environment on attribute
if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) {
if (Message) {
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index e5cf3037aedef..0d6800bb1bc3c 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -411,10 +411,11 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
std::string PlatformName(
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
- TI.getTriple().getEnvironmentName()));
+ TI.getTriple().getEnvironment()));
llvm::StringRef AttrEnvironment =
AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName(
- AA->getEnvironment()->getName())
+ AvailabilityAttr::getEnvironmentType(
+ AA->getEnvironment()->getName()))
: "";
bool UseEnvironment =
(!AttrEnvironment.empty() && !TargetEnvironment.empty());
@@ -845,10 +846,11 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
std::string PlatformName(
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
- TI.getTriple().getEnvironmentName()));
+ TI.getTriple().getEnvironment()));
llvm::StringRef AttrEnvironment =
AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName(
- AA->getEnvironment()->getName())
+ AvailabilityAttr::getEnvironmentType(
+ AA->getEnvironment()->getName()))
: "";
bool UseEnvironment =
(!AttrEnvironment.empty() && !TargetEnvironment.empty());
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 6e407cfc4e375..cb58bebd029c2 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -311,8 +311,6 @@ namespace {
/// the entry points.
class DiagnoseHLSLAvailability
: public RecursiveASTVisitor<DiagnoseHLSLAvailability> {
- // HEKOTAS this is probably not needed
- // typedef RecursiveASTVisitor<DiagnoseHLSLAvailability> Base;
Sema &SemaRef;
@@ -345,34 +343,57 @@ class DiagnoseHLSLAvailability
// depend only on shader model version because they would be duplicate.
bool ReportOnlyShaderStageIssues;
+ // Helper methods for dealing with current stage context / environment
void SetShaderStageContext(HLSLShaderAttr::ShaderType ShaderType) {
assert((((unsigned)1) << (unsigned)ShaderType) != 0 &&
"ShaderType is too big for this bitmap");
CurrentShaderEnvironment = HLSLShaderAttr::getTypeAsEnvironment(ShaderType);
CurrentShaderStageBit = (1 << ShaderType);
}
+
void SetUnknownShaderStageContext() {
CurrentShaderEnvironment =
llvm::Triple::EnvironmentType::UnknownEnvironment;
CurrentShaderStageBit = (1 << 31);
}
+
llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() {
return CurrentShaderEnvironment;
}
+
bool InUnknownShaderStageContext() {
return CurrentShaderEnvironment ==
llvm::Triple::EnvironmentType::UnknownEnvironment;
}
+ // Helper methods for dealing with shader stage bitmap
+ void AddToScannedFunctions(const FunctionDecl *FD) {
+ unsigned &ScannedStages = ScannedDecls.getOrInsertDefault(FD);
+ ScannedStages |= CurrentShaderStageBit;
+ }
+
+ unsigned GetScannedStages(const FunctionDecl *FD) {
+ return ScannedDecls.getOrInsertDefault(FD);
+ }
+
+ bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {
+ return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));
+ }
+
+ bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {
+ return ScannerStages & CurrentShaderStageBit;
+ }
+
+ static bool NeverBeenScanned(unsigned ScannedStages) {
+ return ScannedStages == 0;
+ }
+
// Scanning methods
void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);
void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,
SourceRange Range);
const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);
bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);
- bool WasAlreadyScannedInCurrentShaderStage(const FunctionDecl *FD,
- bool *WasNeverScanned = nullptr);
- void AddToScannedFunctions(const FunctionDecl *FD);
public:
DiagnoseHLSLAvailability(Sema &SemaRef) : SemaRef(SemaRef) {}
@@ -396,23 +417,6 @@ class DiagnoseHLSLAvailability
}
};
-// Returns true if the function has already been scanned in the current
-// shader environment. WasNeverScanned will be set to true if the function
-// has never been scanned before for any shader environment.
-bool DiagnoseHLSLAvailability::WasAlreadyScannedInCurrentShaderStage(
- const FunctionDecl *FD, bool *WasNeverScanned) {
- const unsigned &ScannedStages = ScannedDecls.getOrInsertDefault(FD);
- if (WasNeverScanned)
- *WasNeverScanned = (ScannedStages == 0);
- return ScannedStages & CurrentShaderStageBit;
-}
-
-// Marks the function as scanned in the current shader environment
-void DiagnoseHLSLAvailability::AddToScannedFunctions(const FunctionDecl *FD) {
- unsigned &ScannedStages = ScannedDecls.getOrInsertDefault(FD);
- ScannedStages |= CurrentShaderStageBit;
-}
-
void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
Expr *RefExpr) {
assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&
@@ -421,7 +425,7 @@ void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,
// has a definition -> add to stack to be scanned
const FunctionDecl *FDWithBody = nullptr;
if (FD->hasBody(FDWithBody)) {
- if (!WasAlreadyScannedInCurrentShaderStage(FDWithBody))
+ if (!WasAlreadyScannedInCurrentStage(FDWithBody))
DeclsToScan.push_back(FDWithBody);
return;
}
@@ -475,18 +479,14 @@ void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
DeclsToScan.pop_back();
// Decl was already scanned
- bool WasNeverScanned;
- if (WasAlreadyScannedInCurrentShaderStage(FD, &WasNeverScanned))
+ const unsigned ScannedStages = GetScannedStages(FD);
+ if (WasAlreadyScannedInCurrentStage(ScannedStages))
continue;
- ReportOnlyShaderStageIssues = !WasNeverScanned;
+ ReportOnlyShaderStageIssues = NeverBeenScanned(ScannedStages);
AddToScannedFunctions(FD);
-
- Stmt *Body = FD->getBody();
- assert(Body && "full definition with body expected here");
-
- TraverseStmt(Body);
+ TraverseStmt(FD->getBody());
}
}
@@ -548,21 +548,21 @@ void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
// Do not diagnose shade-stage-specific availability when the shader stage
// context is unknown
- if (InUnknownShaderStageContext() && AA->getEnvironment() != nullptr) {
+ if (InUnknownShaderStageContext() && AA->getEnvironment() != nullptr)
return;
- }
// Emit diagnostic message
const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
llvm::StringRef PlatformName(
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
- llvm::StringRef CurrentEnvStr = AvailabilityAttr::getPrettyEnviromentName(
- AvailabilityAttr::getEnvironmentString(GetCurrentShaderEnvironment()));
+ llvm::StringRef CurrentEnvStr =
+ AvailabilityAttr::getPrettyEnviromentName(GetCurrentShaderEnvironment());
llvm::StringRef AttrEnvStr = AA->getEnvironment()
? AvailabilityAttr::getPrettyEnviromentName(
- AA->getEnvironment()->getName())
+ AvailabilityAttr::getEnvironmentType(
+ AA->getEnvironment()->getName()))
: "";
bool UseEnvironment = !AttrEnvStr.empty();
>From 0ac393c6d439471945017d9501df93e1ae072a38 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 24 May 2024 11:11:55 -0700
Subject: [PATCH 7/9] Fix bug
---
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 cb58bebd029c2..bb0d52396182c 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -483,7 +483,7 @@ void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {
if (WasAlreadyScannedInCurrentStage(ScannedStages))
continue;
- ReportOnlyShaderStageIssues = NeverBeenScanned(ScannedStages);
+ ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
AddToScannedFunctions(FD);
TraverseStmt(FD->getBody());
>From df2854335dd34c42d29f214dd87da814fa4c1819 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 24 May 2024 12:41:57 -0700
Subject: [PATCH 8/9] Code review feedback and add more tests
---
clang/include/clang/Basic/Attr.td | 58 +++++++++----------
clang/lib/Sema/SemaHLSL.cpp | 23 ++++----
.../avail-diag-default-compute.hlsl | 21 +++++++
.../Availability/avail-diag-default-lib.hlsl | 24 +++++++-
.../avail-diag-relaxed-compute.hlsl | 21 +++++++
.../Availability/avail-diag-relaxed-lib.hlsl | 24 +++++++-
6 files changed, 129 insertions(+), 42 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index a17539130545c..e499323612b0e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1062,21 +1062,21 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
}
static llvm::StringRef getPrettyEnviromentName(llvm::Triple::EnvironmentType EnvironmentType) {
switch (EnvironmentType) {
- case llvm::Triple::EnvironmentType::Pixel: return "pixel shader";
- case llvm::Triple::EnvironmentType::Vertex: return "vertex shader";
- case llvm::Triple::EnvironmentType::Geometry: return "geometry shader";
- case llvm::Triple::EnvironmentType::Hull: return "hull shader";
- case llvm::Triple::EnvironmentType::Domain: return "domain shader";
- case llvm::Triple::EnvironmentType::Compute: return "compute shader";
- case llvm::Triple::EnvironmentType::RayGeneration: return "raygeneration shader";
- case llvm::Triple::EnvironmentType::Intersection: return "intersection shader";
- case llvm::Triple::EnvironmentType::AnyHit: return "anyhit shader";
- case llvm::Triple::EnvironmentType::ClosestHit: return "closesthit shader";
- case llvm::Triple::EnvironmentType::Miss: return "miss shader";
- case llvm::Triple::EnvironmentType::Callable: return "callable shader";
- case llvm::Triple::EnvironmentType::Mesh: return "mesh shader";
- case llvm::Triple::EnvironmentType::Amplification: return "amplification shader";
- case llvm::Triple::EnvironmentType::Library: return "shader library";
+ case llvm::Triple::Pixel: return "pixel shader";
+ case llvm::Triple::Vertex: return "vertex shader";
+ case llvm::Triple::Geometry: return "geometry shader";
+ case llvm::Triple::Hull: return "hull shader";
+ case llvm::Triple::Domain: return "domain shader";
+ case llvm::Triple::Compute: return "compute shader";
+ case llvm::Triple::RayGeneration: return "raygeneration shader";
+ case llvm::Triple::Intersection: return "intersection shader";
+ case llvm::Triple::AnyHit: return "anyhit shader";
+ case llvm::Triple::ClosestHit: return "closesthit shader";
+ case llvm::Triple::Miss: return "miss shader";
+ case llvm::Triple::Callable: return "callable shader";
+ case llvm::Triple::Mesh: return "mesh shader";
+ case llvm::Triple::Amplification: return "amplification shader";
+ case llvm::Triple::Library: return "shader library";
default: return "";
}
}
@@ -4492,20 +4492,20 @@ def HLSLShader : InheritableAttr {
let AdditionalMembers =
[{static llvm::Triple::EnvironmentType getTypeAsEnvironment(HLSLShaderAttr::ShaderType ShaderType) {
switch (ShaderType) {
- case HLSLShaderAttr::Pixel: return llvm::Triple::EnvironmentType::Pixel;
- case HLSLShaderAttr::Vertex: return llvm::Triple::EnvironmentType::Vertex;
- case HLSLShaderAttr::Geometry: return llvm::Triple::EnvironmentType::Geometry;
- case HLSLShaderAttr::Hull: return llvm::Triple::EnvironmentType::Hull;
- case HLSLShaderAttr::Domain: return llvm::Triple::EnvironmentType::Domain;
- case HLSLShaderAttr::Compute: return llvm::Triple::EnvironmentType::Compute;
- case HLSLShaderAttr::RayGeneration: return llvm::Triple::EnvironmentType::RayGeneration;
- case HLSLShaderAttr::Intersection: return llvm::Triple::EnvironmentType::Intersection;
- case HLSLShaderAttr::AnyHit: return llvm::Triple::EnvironmentType::AnyHit;
- case HLSLShaderAttr::ClosestHit: return llvm::Triple::EnvironmentType::ClosestHit;
- case HLSLShaderAttr::Miss: return llvm::Triple::EnvironmentType::Miss;
- case HLSLShaderAttr::Callable: return llvm::Triple::EnvironmentType::Callable;
- case HLSLShaderAttr::Mesh: return llvm::Triple::EnvironmentType::Mesh;
- case HLSLShaderAttr::Amplification: return llvm::Triple::EnvironmentType::Amplification;
+ case HLSLShaderAttr::Pixel: return llvm::Triple::Pixel;
+ case HLSLShaderAttr::Vertex: return llvm::Triple::Vertex;
+ case HLSLShaderAttr::Geometry: return llvm::Triple::Geometry;
+ case HLSLShaderAttr::Hull: return llvm::Triple::Hull;
+ case HLSLShaderAttr::Domain: return llvm::Triple::Domain;
+ case HLSLShaderAttr::Compute: return llvm::Triple::Compute;
+ case HLSLShaderAttr::RayGeneration: return llvm::Triple::RayGeneration;
+ case HLSLShaderAttr::Intersection: return llvm::Triple::Intersection;
+ case HLSLShaderAttr::AnyHit: return llvm::Triple::AnyHit;
+ case HLSLShaderAttr::ClosestHit: return llvm::Triple::ClosestHit;
+ case HLSLShaderAttr::Miss: return llvm::Triple::Miss;
+ case HLSLShaderAttr::Callable: return llvm::Triple::Callable;
+ case HLSLShaderAttr::Mesh: return llvm::Triple::Mesh;
+ case HLSLShaderAttr::Amplification: return llvm::Triple::Amplification;
}
}
}];
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index bb0d52396182c..5c773de138aae 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -301,13 +301,13 @@ namespace {
/// and relaxed mode
///
/// The goal of this diagnostic is to emit an error or warning when an
-/// unavailable API is found in a code that is reachable from the shader
-/// entry function or from an exported function (when compiling shader
+/// unavailable API is found in code that is reachable from the shader
+/// entry function or from an exported function (when compiling a shader
/// library).
///
/// This is done by traversing the AST of all shader entry point functions
/// and of all exported functions, and any functions that are refrenced
-/// from this AST. In other words, any function that are reachable from
+/// from this AST. In other words, any functions that are reachable from
/// the entry points.
class DiagnoseHLSLAvailability
: public RecursiveASTVisitor<DiagnoseHLSLAvailability> {
@@ -317,9 +317,9 @@ class DiagnoseHLSLAvailability
// Stack of functions to be scaned
llvm::SmallVector<const FunctionDecl *, 8> DeclsToScan;
- // List of functions that were already scanned and in which environment.
+ // Tracks which environments functions have been scanned in.
//
- // Maps FunctionDecl to a unsigned number that represents a set of shader
+ // Maps FunctionDecl to an unsigned number that represents the set of shader
// environments the function has been scanned for.
// Since HLSLShaderAttr::ShaderType enum is generated from Attr.td and is
// defined without any assigned values, it is guaranteed to be numbered
@@ -331,6 +331,8 @@ class DiagnoseHLSLAvailability
// environment, the value will be 0x21 (100001 binary) because
// (int)HLSLShaderAttr::ShaderType::Pixel == 1 and
// (int)HLSLShaderAttr::ShaderType::Compute == 5.
+ // A FunctionDecl is mapped to 0 (or not included in the map) if it has not
+ // been scanned in any environment.
llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;
// Do not access these directly, use the get/set methods below to make
@@ -346,24 +348,23 @@ class DiagnoseHLSLAvailability
// Helper methods for dealing with current stage context / environment
void SetShaderStageContext(HLSLShaderAttr::ShaderType ShaderType) {
assert((((unsigned)1) << (unsigned)ShaderType) != 0 &&
+ (((unsigned)1) << (unsigned)ShaderType) != 31 &&
"ShaderType is too big for this bitmap");
CurrentShaderEnvironment = HLSLShaderAttr::getTypeAsEnvironment(ShaderType);
CurrentShaderStageBit = (1 << ShaderType);
}
void SetUnknownShaderStageContext() {
- CurrentShaderEnvironment =
- llvm::Triple::EnvironmentType::UnknownEnvironment;
+ CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
CurrentShaderStageBit = (1 << 31);
}
- llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() {
+ llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
return CurrentShaderEnvironment;
}
- bool InUnknownShaderStageContext() {
- return CurrentShaderEnvironment ==
- llvm::Triple::EnvironmentType::UnknownEnvironment;
+ bool InUnknownShaderStageContext() const {
+ return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;
}
// Helper methods for dealing with shader stage bitmap
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
index 80a40adede0dd..664393ea5ebf6 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
@@ -4,6 +4,9 @@
__attribute__((availability(shadermodel, introduced = 6.5)))
float fx(float); // #fx
+__attribute__((availability(shadermodel, introduced = 6.6)))
+half fx(half); // #fx_half
+
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
float fy(float); // #fy
@@ -70,6 +73,22 @@ T aliveTemp(T f) {
return 0;
}
+template<typename T> T aliveTemp2(T f) {
+ // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
+ // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
+ // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ return fx(f); // #aliveTemp2_fx_call
+}
+
+half test(half x) {
+ return aliveTemp2(x);
+}
+
+float test(float x) {
+ return aliveTemp2(x);
+}
+
class MyClass
{
float F;
@@ -94,5 +113,7 @@ float main() {
float a = alive(f);
float b = aliveTemp<float>(f); // #aliveTemp_inst
float c = C.makeF();
+ float d = test((float)1.0);
+ float e = test((half)1.0);
return a * b * c;
}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
index 7290bdb6ce029..5367bcc846238 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
@@ -4,6 +4,9 @@
__attribute__((availability(shadermodel, introduced = 6.5)))
float fx(float); // #fx
+__attribute__((availability(shadermodel, introduced = 6.6)))
+half fx(half); // #fx_half
+
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
float fy(float); // #fy
@@ -74,6 +77,22 @@ T aliveTemp(T f) {
return 0;
}
+template<typename T> T aliveTemp2(T f) {
+ // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
+ // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
+ // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ return fx(f); // #aliveTemp2_fx_call
+}
+
+half test(half x) {
+ return aliveTemp2(x);
+}
+
+float test(float x) {
+ return aliveTemp2(x);
+}
+
class MyClass
{
float F;
@@ -102,7 +121,10 @@ float main();
float main() {
float f = 3;
MyClass C = { 1.0f };
- float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
+ float a = alive(f);
+ float b = aliveTemp<float>(f); // #aliveTemp_inst
float c = C.makeF();
+ float d = test((float)1.0);
+ float e = test((half)1.0);
return a * b * c;
}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
index dfb0000db99cd..5230e81e8a2c0 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
@@ -4,6 +4,9 @@
__attribute__((availability(shadermodel, introduced = 6.5)))
float fx(float); // #fx
+__attribute__((availability(shadermodel, introduced = 6.6)))
+half fx(half); // #fx_half
+
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
float fy(float); // #fy
@@ -70,6 +73,22 @@ T aliveTemp(T f) {
return 0;
}
+template<typename T> T aliveTemp2(T f) {
+ // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
+ // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
+ // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ return fx(f); // #aliveTemp2_fx_call
+}
+
+half test(half x) {
+ return aliveTemp2(x);
+}
+
+float test(float x) {
+ return aliveTemp2(x);
+}
+
class MyClass
{
float F;
@@ -94,5 +113,7 @@ float main() {
float a = alive(f);
float b = aliveTemp<float>(f); // #aliveTemp_inst
float c = C.makeF();
+ float d = test((float)1.0);
+ float e = test((half)1.0);
return a * b * c;
}
diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
index 4d6e06faef8ac..dca615ed292b1 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
@@ -4,6 +4,9 @@
__attribute__((availability(shadermodel, introduced = 6.5)))
float fx(float); // #fx
+__attribute__((availability(shadermodel, introduced = 6.6)))
+half fx(half); // #fx_half
+
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
float fy(float); // #fy
@@ -74,6 +77,22 @@ T aliveTemp(T f) {
return 0;
}
+template<typename T> T aliveTemp2(T f) {
+ // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
+ // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
+ // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
+ // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
+ return fx(f); // #aliveTemp2_fx_call
+}
+
+half test(half x) {
+ return aliveTemp2(x);
+}
+
+float test(float x) {
+ return aliveTemp2(x);
+}
+
class MyClass
{
float F;
@@ -102,7 +121,10 @@ float main();
float main() {
float f = 3;
MyClass C = { 1.0f };
- float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
+ float a = alive(f);
+ float b = aliveTemp<float>(f); // #aliveTemp_inst
float c = C.makeF();
+ float d = test((float)1.0);
+ float e = test((half)1.0);
return a * b * c;
}
>From 7feed6e5867e5d4e91310aef400b1c121a239f31 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 28 May 2024 13:52:52 -0700
Subject: [PATCH 9/9] Add static assert for the max shader type value
---
clang/include/clang/Basic/Attr.td | 5 ++++-
clang/lib/Sema/SemaHLSL.cpp | 2 ++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index e499323612b0e..1fdb7a3f78085 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4490,7 +4490,10 @@ def HLSLShader : InheritableAttr {
];
let Documentation = [HLSLSV_ShaderTypeAttrDocs];
let AdditionalMembers =
-[{static llvm::Triple::EnvironmentType getTypeAsEnvironment(HLSLShaderAttr::ShaderType ShaderType) {
+[{
+ static const unsigned ShaderTypeMaxValue = (unsigned)HLSLShaderAttr::Amplification;
+
+ static llvm::Triple::EnvironmentType getTypeAsEnvironment(HLSLShaderAttr::ShaderType ShaderType) {
switch (ShaderType) {
case HLSLShaderAttr::Pixel: return llvm::Triple::Pixel;
case HLSLShaderAttr::Vertex: return llvm::Triple::Vertex;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5c773de138aae..dd0b36837fd7b 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -347,6 +347,8 @@ class DiagnoseHLSLAvailability
// Helper methods for dealing with current stage context / environment
void SetShaderStageContext(HLSLShaderAttr::ShaderType ShaderType) {
+ static_assert(HLSLShaderAttr::ShaderTypeMaxValue < 31,
+ "ShaderType is too big for this bitmap");
assert((((unsigned)1) << (unsigned)ShaderType) != 0 &&
(((unsigned)1) << (unsigned)ShaderType) != 31 &&
"ShaderType is too big for this bitmap");
More information about the cfe-commits
mailing list