[HLSL] Default and Relaxed Availability Diagnostics (#92704)

Implements HLSL availability diagnostics' default and relaxed mode.

HLSL availability diagnostics emits errors or warning when unavailable
shader APIs are used. Unavailable shader APIs are APIs that are exposed
in HLSL code but are not available in the target shader stage or shader
model version.

In the default mode the compiler emits an error when an unavailable API
is found in a code that is reachable from the shader entry point
function. In the future this check will also extended to exported
library functions (#92073). The relaxed diagnostic mode is the same
except the compiler emits a warning. This mode is enabled by
``-Wno-error=hlsl-availability``.

See HLSL Availability Diagnostics design doc
[here](https://github.com/llvm/llvm-project/blob/main/clang/docs/HLSL/AvailabilityDiagnostics.rst)
for more details.

Fixes #90095
This commit is contained in:
Helena Kotas 2024-05-29 21:52:20 -07:00 committed by GitHub
parent 02c6845c76
commit 8890209ead
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 941 additions and 51 deletions

View File

@ -1060,18 +1060,10 @@ 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("mesh", "mesh shader")
.Case("amplification", "amplification shader")
.Case("library", "shader library")
.Default(Environment);
static llvm::StringRef getPrettyEnviromentName(llvm::Triple::EnvironmentType EnvironmentType) {
if (EnvironmentType >= llvm::Triple::Pixel && EnvironmentType <= llvm::Triple::Amplification)
return llvm::Triple::getEnvironmentTypeName(EnvironmentType);
return "";
}
static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environment) {
return llvm::StringSwitch<llvm::Triple::EnvironmentType>(Environment)
@ -1081,6 +1073,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)
@ -4480,6 +4478,29 @@ def HLSLShader : InheritableAttr {
"Miss", "Callable", "Mesh", "Amplification"]>
];
let Documentation = [HLSLSV_ShaderTypeAttrDocs];
let AdditionalMembers =
[{
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;
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;
}
}
}];
}
def HLSLResource : InheritableAttr {

View File

@ -1517,6 +1517,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">;

View File

@ -12239,6 +12239,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">;

View File

@ -49,6 +49,7 @@ public:
void DiagnoseAttrStageMismatch(
const Attr *A, HLSLShaderAttr::ShaderType Stage,
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
};
} // namespace clang

View File

@ -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) {

View File

@ -1357,6 +1357,10 @@ 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

View File

@ -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;
@ -409,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());
@ -438,6 +441,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()) {
@ -839,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());
@ -865,6 +873,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

View File

@ -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,296 @@ 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 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 functions that are reachable from
/// the entry points.
class DiagnoseHLSLAvailability
: public RecursiveASTVisitor<DiagnoseHLSLAvailability> {
Sema &SemaRef;
// Stack of functions to be scaned
llvm::SmallVector<const FunctionDecl *, 8> DeclsToScan;
// Tracks which environments functions have been scanned in.
//
// 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
// 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.
// 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
// 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;
// Helper methods for dealing with current stage context / environment
void SetShaderStageContext(HLSLShaderAttr::ShaderType ShaderType) {
static_assert(sizeof(unsigned) >= 4);
assert((unsigned)ShaderType < 31); // 31 is reserved for "unknown"
CurrentShaderEnvironment = HLSLShaderAttr::getTypeAsEnvironment(ShaderType);
CurrentShaderStageBit = (1 << ShaderType);
}
void SetUnknownShaderStageContext() {
CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;
CurrentShaderStageBit = (1 << 31);
}
llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {
return CurrentShaderEnvironment;
}
bool InUnknownShaderStageContext() const {
return CurrentShaderEnvironment == llvm::Triple::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);
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;
}
};
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 (!WasAlreadyScannedInCurrentStage(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
const unsigned ScannedStages = GetScannedStages(FD);
if (WasAlreadyScannedInCurrentStage(ScannedStages))
continue;
ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);
AddToScannedFunctions(FD);
TraverseStmt(FD->getBody());
}
}
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(GetCurrentShaderEnvironment());
llvm::StringRef AttrEnvStr = AA->getEnvironment()
? AvailabilityAttr::getPrettyEnviromentName(
AvailabilityAttr::getEnvironmentType(
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);
}

View File

@ -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-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}}
// expected-error@#f6_call {{'f6' is only available in compute 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 environment here, but the deployment target is Shader Model 5.0}}
unsigned F = f6(); // #f6_call
// expected-warning@#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}}
// expected-error@#f7_call {{'f7' is unavailable}}
// expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh environment here, but the deployment target is Shader Model 5.0 compute environment}}
unsigned G = f7(); // #f7_call
unsigned H = f8();

View File

@ -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-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}}
// expected-error@#f7_call {{'f7' is only available in mesh 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 environment here, but the deployment target is Shader Model 5.0 mesh environment}}
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-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}}
// expected-error@#f8_call {{'f8' is only available in mesh 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 environment here, but the deployment target is Shader Model 5.0 mesh environment}}
unsigned H = f8(); // #f8_call
return 0;

View File

@ -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();

View File

@ -0,0 +1,119 @@
// 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 = 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
__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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute environment}}
float C = fz(f); // #aliveTemp_fz_call
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;
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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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();
float d = test((float)1.0);
float e = test((half)1.0);
return a * b * c;
}

View File

@ -0,0 +1,130 @@
// 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 = 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
__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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute environment}}
float C = fz(f); // #aliveTemp_fz_call
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;
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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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();
float d = test((float)1.0);
float e = test((half)1.0);
return a * b * c;
}

View File

@ -0,0 +1,119 @@
// 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 = 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
__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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute environment}}
float C = fz(f); // #aliveTemp_fz_call
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;
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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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();
float d = test((float)1.0);
float e = test((half)1.0);
return a * b * c;
}

View File

@ -0,0 +1,130 @@
// 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 = 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
__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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute environment}}
float C = fz(f); // #aliveTemp_fz_call
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;
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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 compute 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();
float d = test((float)1.0);
float e = test((half)1.0);
return a * b * c;
}

View File

@ -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 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 environment here, but the deployment target is Shader Model 6.0 compute 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 environment here, but the deployment target is Shader Model 6.0 pixel 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);
}

View File

@ -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@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
}