[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:
parent
02c6845c76
commit
8890209ead
@ -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 {
|
||||
|
@ -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">;
|
||||
|
||||
|
@ -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">;
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
119
clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
Normal file
119
clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
Normal 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;
|
||||
}
|
130
clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
Normal file
130
clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
Normal 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;
|
||||
}
|
119
clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
Normal file
119
clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
Normal 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;
|
||||
}
|
130
clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
Normal file
130
clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
Normal 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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user