https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/93860
>From 532f10f77c862f6d429366f0d6903773da8fa79b Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 30 May 2024 11:40:27 -0700 Subject: [PATCH 1/3] Implement HLSL strict diagnostic mode --- clang/include/clang/Basic/Attr.td | 5 - clang/include/clang/Basic/LangOptions.def | 2 + clang/include/clang/Driver/Options.td | 9 ++ clang/lib/AST/DeclBase.cpp | 2 +- clang/lib/Sema/SemaAvailability.cpp | 76 ++++++---- clang/lib/Sema/SemaHLSL.cpp | 54 +++++-- .../avail-diag-strict-compute.hlsl | 129 ++++++++++++++++ .../Availability/avail-diag-strict-lib.hlsl | 142 ++++++++++++++++++ 8 files changed, 369 insertions(+), 50 deletions(-) create mode 100644 clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl create mode 100644 clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 2665b7353ca4a..6ac2e3b50ee54 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1060,11 +1060,6 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { .Case("ShaderModel", "shadermodel") .Default(Platform); } -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) .Case("pixel", llvm::Triple::Pixel) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 4061451b2150a..443b49d0e2779 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -276,6 +276,8 @@ LANGOPT(RenderScript , 1, 0, "RenderScript") LANGOPT(HLSL, 1, 0, "HLSL") ENUM_LANGOPT(HLSLVersion, HLSLLangStd, 16, HLSL_Unset, "HLSL Version") +LANGOPT(HLSLStrictAvailability, 1, 0, + "Strict availability diagnostic mode for HLSL built-in functions.") LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device") LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1637a114fcce1..cb380450d0425 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -196,6 +196,10 @@ def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>, DocName<"Target-dependent compilation options">, Visibility<[ClangOption, CLOption]>; +def hlsl_Group : OptionGroup<"<HLSL group>">, Group<f_Group>, + DocName<"HLSL options">, + Visibility<[ClangOption]>; + // Feature groups - these take command line options that correspond directly to // target specific features and can be translated directly from command line // options. @@ -7863,6 +7867,11 @@ def finclude_default_header : Flag<["-"], "finclude-default-header">, def fdeclare_opencl_builtins : Flag<["-"], "fdeclare-opencl-builtins">, HelpText<"Add OpenCL builtin function declarations (experimental)">; +def fhlsl_strict_availability : Flag<["-"], "fhlsl-strict-availability">, + HelpText<"Enables strict availability diagnostic mode for HLSL built-in functions.">, + Group<hlsl_Group>, + MarshallingInfoFlag<LangOpts<"HLSLStrictAvailability">>; + def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">, HelpText<"Preserve 3-component vector type">, MarshallingInfoFlag<CodeGenOpts<"PreserveVec3Type">>, diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index ffb22194bce52..f481019eff51a 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -669,7 +669,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, IdentifierInfo *IIEnv = A->getEnvironment(); StringRef TargetEnv = Context.getTargetInfo().getTriple().getEnvironmentName(); - StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName( + StringRef EnvName = llvm::Triple::getEnvironmentTypeName( Context.getTargetInfo().getTriple().getEnvironment()); // Matching environment or no environment on attribute if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) { diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 330cd602297d4..0e448c8b13985 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -229,9 +229,7 @@ shouldDiagnoseAvailabilityByDefault(const ASTContext &Context, ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13); break; case llvm::Triple::ShaderModel: - // FIXME: This will be updated when HLSL strict diagnostic mode - // is implemented (issue #90096) - return false; + return Context.getLangOpts().HLSLStrictAvailability; default: // New targets should always warn about availability. return Triple.getVendor() == llvm::Triple::Apple; @@ -410,13 +408,10 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, const TargetInfo &TI = S.getASTContext().getTargetInfo(); std::string PlatformName( AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); - llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName( - TI.getTriple().getEnvironment())); + llvm::StringRef TargetEnvironment( + llvm::Triple::getEnvironmentTypeName(TI.getTriple().getEnvironment())); llvm::StringRef AttrEnvironment = - AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName( - AvailabilityAttr::getEnvironmentType( - AA->getEnvironment()->getName())) - : ""; + AA->getEnvironment() ? AA->getEnvironment()->getName() : ""; bool UseEnvironment = (!AttrEnvironment.empty() && !TargetEnvironment.empty()); @@ -834,34 +829,55 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( OffendingDecl)) return; - // We would like to emit the diagnostic even if -Wunguarded-availability is - // not specified for deployment targets >= to iOS 11 or equivalent or - // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or - // later. - bool UseNewDiagKind = shouldDiagnoseAvailabilityByDefault( - SemaRef.Context, - SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced); - const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo(); + + // In HLSL, emit diagnostic here during parsing only if the diagnostic + // mode is set to strict (-fhlsl-strict-availability), and either the decl + // availability is not restricted to a specific environment/shader stage, + // or the target stage is known (= it is not shader library). + const LangOptions &LandOpts = SemaRef.getLangOpts(); + if (LandOpts.HLSL) { + if (!LandOpts.HLSLStrictAvailability || + (AA->getEnvironment() != nullptr && + TI.getTriple().getEnvironment() == + llvm::Triple::EnvironmentType::Library)) + return; + } + std::string PlatformName( AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); - llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName( - TI.getTriple().getEnvironment())); + llvm::StringRef TargetEnvironment(TI.getTriple().getEnvironmentName()); llvm::StringRef AttrEnvironment = - AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName( - AvailabilityAttr::getEnvironmentType( - AA->getEnvironment()->getName())) - : ""; + AA->getEnvironment() ? AA->getEnvironment()->getName() : ""; bool UseEnvironment = (!AttrEnvironment.empty() && !TargetEnvironment.empty()); - unsigned DiagKind = - EnvironmentMatchesOrNone - ? (UseNewDiagKind ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability) - : (UseNewDiagKind - ? diag::warn_unguarded_availability_unavailable_new - : diag::warn_unguarded_availability_unavailable); + unsigned DiagKind; + if (SemaRef.getLangOpts().HLSL) { + // For HLSL, use diagnostic from HLSLAvailability group which + // are reported as errors in default and in strict diagnostic mode + // (-fhlsl-strict-availability) and as warnings in relaxed diagnostic + // mode (-Wno-error=hlsl-availability) + DiagKind = EnvironmentMatchesOrNone + ? diag::warn_hlsl_availability + : diag::warn_hlsl_availability_unavailable; + + } else { + // For iOS, emit the diagnostic even if -Wunguarded-availability is + // not specified for deployment targets >= to iOS 11 or equivalent or + // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or + // later. + bool UseNewDiagKind = shouldDiagnoseAvailabilityByDefault( + SemaRef.Context, + SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced); + + DiagKind = EnvironmentMatchesOrNone + ? (UseNewDiagKind ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability) + : (UseNewDiagKind + ? diag::warn_unguarded_availability_unavailable_new + : diag::warn_unguarded_availability_unavailable); + } SemaRef.Diag(Range.getBegin(), DiagKind) << Range << D << PlatformName << Introduced.getAsString() diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 9e614ae99f37d..87a6043a064c7 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -306,7 +306,7 @@ namespace { /// 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 +/// and of all exported functions, and any functions that are referenced /// from this AST. In other words, any functions that are reachable from /// the entry points. class DiagnoseHLSLAvailability @@ -536,9 +536,34 @@ DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) { void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA, SourceRange Range) { - if (ReportOnlyShaderStageIssues && !AA->getEnvironment()) - return; + IdentifierInfo *IIEnv = AA->getEnvironment(); + + if (!IIEnv) { + // The availability attribute does not have environment -> it depends only + // on shader model version and not on specific the shader stage. + + // Skip emitting the diagnostics if the diagnostic mode is not set to + // strict (-fhlsl-strict-availability) because all relevant diagnostics + // were already emitted in the DiagnoseUnguardedAvailability scan + // (SemaAvailability.cpp). + if (SemaRef.getLangOpts().HLSLStrictAvailability) + return; + + // Do not report shader-stage-independent issues if scanning a function + // that was already scanned in a different shader stage context (they would + // be duplicate) + if (ReportOnlyShaderStageIssues) + return; + + } else { + // The availability attribute has environment -> we need to know + // the current stage context to property diagnose it. + if (InUnknownShaderStageContext()) + return; + } + + // Check introduced version and if environment matches bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA); VersionTuple Introduced = AA->getIntroduced(); VersionTuple TargetVersion = @@ -547,24 +572,16 @@ void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D, 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::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment()); - llvm::StringRef AttrEnvStr = AA->getEnvironment() - ? AvailabilityAttr::getPrettyEnviromentName( - AvailabilityAttr::getEnvironmentType( - AA->getEnvironment()->getName())) - : ""; + llvm::StringRef AttrEnvStr = + AA->getEnvironment() ? AA->getEnvironment()->getName() : ""; bool UseEnvironment = !AttrEnvStr.empty(); if (EnvironmentMatches) { @@ -585,5 +602,14 @@ void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D, } // namespace void SemaHLSL::DiagnoseAvailabilityViolations(TranslationUnitDecl *TU) { + // Skip running the diagnostics scan if the diagnostic mode is + // strict (-fhlsl-strict-availability) and the target shader stage is known + // because all relevant diagnostics were already emitted in the + // DiagnoseUnguardedAvailability scan (SemaAvailability.cpp). + const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo(); + if (SemaRef.getLangOpts().HLSLStrictAvailability && + TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library) + return; + DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU); } diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl new file mode 100644 index 0000000000000..b67e10c9a9017 --- /dev/null +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl @@ -0,0 +1,129 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ +// RUN: -fhlsl-strict-availability -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) { + // expected-error@#also_dead_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_dead_fx_call + // expected-error@#also_dead_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_dead_fy_call + // expected-error@#also_dead_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_dead_fz_call + return 0; +} + +float dead(float f) { + // expected-error@#dead_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); // #dead_fx_call + // expected-error@#dead_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); // #dead_fy_call + // expected-error@#dead_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); // #dead_fz_call + + 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@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp<float>' requested here}} + // 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); // expected-note {{in instantiation of function template specialization 'aliveTemp2<half>' requested here}} +} + +float test(float x) { + return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<float>' requested here}} +} + +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 + } +}; + +[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; +} \ No newline at end of file diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl new file mode 100644 index 0000000000000..4c9675051e570 --- /dev/null +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl @@ -0,0 +1,142 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ +// RUN: -fhlsl-strict-availability -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 + +// FIXME: all diagnostics marked as FUTURE will come alive when HLSL default +// diagnostic mode is implemented in a future PR which will verify calls in +// all functions that are reachable from the shader library entry points + +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) { + // expected-error@#also_dead_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_dead_fx_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float B = fy(f); // #also_dead_fy_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float C = fz(f); // #also_dead_fz_call + return 0; +} + +float dead(float f) { + // expected-error@#dead_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); // #dead_fx_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float B = fy(f); // #dead_fy_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float C = fz(f); // #dead_fz_call + + 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@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp<float>' requested here}} + // 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); // expected-note {{in instantiation of function template specialization 'aliveTemp2<half>' requested here}} +} + +float test(float x) { + return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<float>' requested here}} +} + +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 + } +}; + +[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; +} \ No newline at end of file >From 33c54e453f978943154f121e29a3c863f0b83e06 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 3 Jun 2024 12:05:14 -0700 Subject: [PATCH 2/3] Move check to ShouldDiagnoseAvailabilityInContext --- clang/lib/Sema/SemaAvailability.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 0e448c8b13985..3eaf25709e91a 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -157,6 +157,18 @@ static bool ShouldDiagnoseAvailabilityInContext( } } + // In HLSL, emit diagnostic during parsing only if the diagnostic + // mode is set to strict (-fhlsl-strict-availability), and either the decl + // availability is not restricted to a specific environment/shader stage, + // or the target stage is known (= it is not shader library). + if (S.getLangOpts().HLSL) { + if (!S.getLangOpts().HLSLStrictAvailability || + (DeclEnv != nullptr && + S.getASTContext().getTargetInfo().getTriple().getEnvironment() == + llvm::Triple::EnvironmentType::Library)) + return false; + } + // Checks if we should emit the availability diagnostic in the context of C. auto CheckContext = [&](const Decl *C) { if (K == AR_NotYetIntroduced) { @@ -830,20 +842,6 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( return; const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo(); - - // In HLSL, emit diagnostic here during parsing only if the diagnostic - // mode is set to strict (-fhlsl-strict-availability), and either the decl - // availability is not restricted to a specific environment/shader stage, - // or the target stage is known (= it is not shader library). - const LangOptions &LandOpts = SemaRef.getLangOpts(); - if (LandOpts.HLSL) { - if (!LandOpts.HLSLStrictAvailability || - (AA->getEnvironment() != nullptr && - TI.getTriple().getEnvironment() == - llvm::Triple::EnvironmentType::Library)) - return; - } - std::string PlatformName( AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); llvm::StringRef TargetEnvironment(TI.getTriple().getEnvironmentName()); >From 78a02c7285a9e7aa7e1bc0ebb0533a34e2e1f4f1 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Tue, 11 Jun 2024 17:18:08 -0700 Subject: [PATCH 3/3] Code review feedback --- clang/lib/Sema/SemaAvailability.cpp | 74 ++++++++++++----------------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 3eaf25709e91a..f6aa8145fc153 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -222,13 +222,16 @@ static bool ShouldDiagnoseAvailabilityInContext( return true; } -static bool -shouldDiagnoseAvailabilityByDefault(const ASTContext &Context, - const VersionTuple &DeploymentVersion, - const VersionTuple &DeclVersion) { +static unsigned getAvailabilityDiagnosticKind( + const ASTContext &Context, const VersionTuple &DeploymentVersion, + const VersionTuple &DeclVersion, bool HasMatchingEnv) { const auto &Triple = Context.getTargetInfo().getTriple(); VersionTuple ForceAvailabilityFromVersion; switch (Triple.getOS()) { + // For iOS, emit the diagnostic even if -Wunguarded-availability is + // not specified for deployment targets >= to iOS 11 or equivalent or + // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or + // later. case llvm::Triple::IOS: case llvm::Triple::TvOS: ForceAvailabilityFromVersion = VersionTuple(/*Major=*/11); @@ -240,14 +243,26 @@ shouldDiagnoseAvailabilityByDefault(const ASTContext &Context, case llvm::Triple::MacOSX: ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13); break; + // For HLSL, use diagnostic from HLSLAvailability group which + // are reported as errors by default and in strict diagnostic mode + // (-fhlsl-strict-availability) and as warnings in relaxed diagnostic + // mode (-Wno-error=hlsl-availability) case llvm::Triple::ShaderModel: - return Context.getLangOpts().HLSLStrictAvailability; + return HasMatchingEnv ? diag::warn_hlsl_availability + : diag::warn_hlsl_availability_unavailable; default: - // New targets should always warn about availability. - return Triple.getVendor() == llvm::Triple::Apple; + // New Apple targets should always warn about availability. + ForceAvailabilityFromVersion = + (Triple.getVendor() == llvm::Triple::Apple) + ? VersionTuple(/*Major=*/0, 0) + : VersionTuple(/*Major=*/(unsigned)-1, (unsigned)-1); } - return DeploymentVersion >= ForceAvailabilityFromVersion || - DeclVersion >= ForceAvailabilityFromVersion; + if (DeploymentVersion >= ForceAvailabilityFromVersion || + DeclVersion >= ForceAvailabilityFromVersion) + return HasMatchingEnv ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability_unavailable_new; + return HasMatchingEnv ? diag::warn_unguarded_availability + : diag::warn_unguarded_availability_unavailable; } static NamedDecl *findEnclosingDeclToAnnotate(Decl *OrigCtx) { @@ -427,16 +442,9 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, bool UseEnvironment = (!AttrEnvironment.empty() && !TargetEnvironment.empty()); - bool UseNewWarning = shouldDiagnoseAvailabilityByDefault( + unsigned DiagKind = getAvailabilityDiagnosticKind( S.Context, S.Context.getTargetInfo().getPlatformMinVersion(), - Introduced); - - unsigned DiagKind = - EnvironmentMatchesOrNone - ? (UseNewWarning ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability) - : (UseNewWarning ? diag::warn_unguarded_availability_unavailable_new - : diag::warn_unguarded_availability_unavailable); + Introduced, EnvironmentMatchesOrNone); S.Diag(Loc, DiagKind) << OffendingDecl << PlatformName << Introduced.getAsString() << UseEnvironment @@ -850,32 +858,10 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( bool UseEnvironment = (!AttrEnvironment.empty() && !TargetEnvironment.empty()); - unsigned DiagKind; - if (SemaRef.getLangOpts().HLSL) { - // For HLSL, use diagnostic from HLSLAvailability group which - // are reported as errors in default and in strict diagnostic mode - // (-fhlsl-strict-availability) and as warnings in relaxed diagnostic - // mode (-Wno-error=hlsl-availability) - DiagKind = EnvironmentMatchesOrNone - ? diag::warn_hlsl_availability - : diag::warn_hlsl_availability_unavailable; - - } else { - // For iOS, emit the diagnostic even if -Wunguarded-availability is - // not specified for deployment targets >= to iOS 11 or equivalent or - // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or - // later. - bool UseNewDiagKind = shouldDiagnoseAvailabilityByDefault( - SemaRef.Context, - SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced); - - DiagKind = EnvironmentMatchesOrNone - ? (UseNewDiagKind ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability) - : (UseNewDiagKind - ? diag::warn_unguarded_availability_unavailable_new - : diag::warn_unguarded_availability_unavailable); - } + unsigned DiagKind = getAvailabilityDiagnosticKind( + SemaRef.Context, + SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced, + EnvironmentMatchesOrNone); SemaRef.Diag(Range.getBegin(), DiagKind) << Range << D << PlatformName << Introduced.getAsString() _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits