[clang] [Clang][HLSL] Add environment parameter to availability attribute (PR #89809)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Tue May 14 09:12:11 PDT 2024
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/89809
>From 22b67d30ca087d6a912183039c87fd1790eedfe4 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 23 Apr 2024 00:49:28 -0700
Subject: [PATCH 1/8] Add environment parameter to clang availability attribute
---
clang/include/clang/Basic/Attr.td | 33 +++++-
clang/include/clang/Basic/AttrDocs.td | 2 +
.../clang/Basic/DiagnosticParseKinds.td | 2 +
.../clang/Basic/DiagnosticSemaKinds.td | 5 +-
clang/include/clang/Parse/Parser.h | 3 +
clang/include/clang/Sema/ParsedAttr.h | 40 ++++---
clang/include/clang/Sema/Sema.h | 5 +-
clang/lib/AST/DeclBase.cpp | 27 ++++-
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 13 ++-
clang/lib/Index/CommentToXML.cpp | 3 +
clang/lib/Parse/ParseDecl.cpp | 20 +++-
clang/lib/Sema/SemaAPINotes.cpp | 3 +-
clang/lib/Sema/SemaAvailability.cpp | 109 +++++++++++++-----
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaDeclAttr.cpp | 34 ++++--
15 files changed, 232 insertions(+), 69 deletions(-)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022d..1b07f4eb40809 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -956,7 +956,7 @@ def Availability : InheritableAttr {
VersionArgument<"deprecated">, VersionArgument<"obsoleted">,
BoolArgument<"unavailable">, StringArgument<"message">,
BoolArgument<"strict">, StringArgument<"replacement">,
- IntArgument<"priority">];
+ IntArgument<"priority">, IdentifierArgument<"environment">];
let AdditionalMembers =
[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) {
return llvm::StringSwitch<llvm::StringRef>(Platform)
@@ -976,7 +976,7 @@ def Availability : InheritableAttr {
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOS (App Extension)")
.Case("swift", "Swift")
- .Case("shadermodel", "HLSL ShaderModel")
+ .Case("shadermodel", "HLSL Shader Model")
.Case("ohos", "OpenHarmony OS")
.Default(llvm::StringRef());
}
@@ -1016,7 +1016,34 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
.Case("visionos_app_extension", "xros_app_extension")
.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::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environment) {
+ return llvm::StringSwitch<llvm::Triple::EnvironmentType>(Environment)
+ .Case("pixel", llvm::Triple::Pixel)
+ .Case("vertex", llvm::Triple::Vertex)
+ .Case("geometry", llvm::Triple::Geometry)
+ .Case("hull", llvm::Triple::Hull)
+ .Case("domain", llvm::Triple::Domain)
+ .Case("compute", llvm::Triple::Compute)
+ .Case("mesh", llvm::Triple::Mesh)
+ .Case("amplification", llvm::Triple::Amplification)
+ .Case("library", llvm::Triple::Library)
+ .Default(llvm::Triple::UnknownEnvironment);
+}
+}];
let HasCustomParsing = 1;
let InheritEvenIfAlreadyPresent = 1;
let Subjects = SubjectList<[Named]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c572..a81163df35ca8 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1593,6 +1593,8 @@ replacement=\ *string-literal*
a warning about use of a deprecated declaration. The Fix-It will replace
the deprecated declaration with the new declaration specified.
+// HEKOTA TODO add docs here
+
Multiple availability attributes can be placed on a declaration, which may
correspond to different platforms. For most platforms, the availability
attribute with the platform corresponding to the target platform will be used;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 66405095d51de..631dc8880fcfc 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1103,6 +1103,8 @@ def err_zero_version : Error<
"version number must have non-zero major, minor, or sub-minor version">;
def err_availability_expected_platform : Error<
"expected a platform name, e.g., 'macos'">;
+def err_availability_expected_environment : Error<
+ "expected an environment name, e.g., 'pixel'">;
// objc_bridge_related attribute
def err_objcbridge_related_expected_related_class : Error<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a2d8bf4e4eb1..2647d84d4041d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3819,6 +3819,9 @@ def note_cannot_use_trivial_abi_reason : Note<
// Availability attribute
def warn_availability_unknown_platform : Warning<
"unknown platform %0 in availability macro">, InGroup<Availability>;
+def warn_availability_unknown_environment : Warning<
+ "unknown environment %0 in availability macro">, InGroup<Availability>;
+
def warn_availability_version_ordering : Warning<
"feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version "
"%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; "
@@ -3851,7 +3854,7 @@ def warn_availability_fuchsia_unavailable_minor : Warning<
InGroup<Availability>;
def warn_unguarded_availability :
- Warning<"%0 is only available on %1 %2 or newer">,
+ Warning<"%0 %select{is only|is not}5 available %select{|in %4 environment }3on %1 %2 %select{or newer|}5">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_unguarded_availability_new :
Warning<warn_unguarded_availability.Summary>,
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 72b2f958a5e62..a6cb96ca4a37c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -151,6 +151,9 @@ class Parser : public CodeCompletionHandler {
/// Identifier for "replacement".
IdentifierInfo *Ident_replacement;
+ /// Identifier for "environment".
+ IdentifierInfo *Ident_environment;
+
/// Identifiers used by the 'external_source_symbol' attribute.
IdentifierInfo *Ident_language, *Ident_defined_in,
*Ident_generated_declaration, *Ident_USR;
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 25a5fa05b21c7..7ad39d1a4942f 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -40,6 +40,7 @@ class LangOptions;
class Sema;
class Stmt;
class TargetInfo;
+struct IdentifierLoc;
/// Represents information about a change in availability for
/// an entity, which is part of the encoding of the 'availability'
@@ -68,12 +69,14 @@ struct AvailabilityData {
AvailabilityChange Changes[NumAvailabilitySlots];
SourceLocation StrictLoc;
const Expr *Replacement;
+ const IdentifierLoc *EnvironmentLoc;
AvailabilityData(const AvailabilityChange &Introduced,
const AvailabilityChange &Deprecated,
const AvailabilityChange &Obsoleted,
- SourceLocation Strict, const Expr *ReplaceExpr)
- : StrictLoc(Strict), Replacement(ReplaceExpr) {
+ SourceLocation Strict, const Expr *ReplaceExpr,
+ const IdentifierLoc *EnvironmentLoc)
+ : StrictLoc(Strict), Replacement(ReplaceExpr), EnvironmentLoc(EnvironmentLoc) {
Changes[IntroducedSlot] = Introduced;
Changes[DeprecatedSlot] = Deprecated;
Changes[ObsoletedSlot] = Obsoleted;
@@ -234,7 +237,7 @@ class ParsedAttr final
const AvailabilityChange &deprecated,
const AvailabilityChange &obsoleted, SourceLocation unavailable,
const Expr *messageExpr, Form formUsed, SourceLocation strict,
- const Expr *replacementExpr)
+ const Expr *replacementExpr, const IdentifierLoc *environmentLoc)
: AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
@@ -243,8 +246,9 @@ class ParsedAttr final
Info(ParsedAttrInfo::get(*this)) {
ArgsUnion PVal(Parm);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
- new (getAvailabilityData()) detail::AvailabilityData(
- introduced, deprecated, obsoleted, strict, replacementExpr);
+ new (getAvailabilityData())
+ detail::AvailabilityData(introduced, deprecated, obsoleted, strict,
+ replacementExpr, environmentLoc);
}
/// Constructor for objc_bridge_related attributes.
@@ -445,6 +449,12 @@ class ParsedAttr final
return getAvailabilityData()->Replacement;
}
+ const IdentifierLoc *getEnvironment() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return getAvailabilityData()->EnvironmentLoc;
+ }
+
const ParsedType &getMatchingCType() const {
assert(getParsedKind() == AT_TypeTagForDatatype &&
"Not a type_tag_for_datatype attribute");
@@ -759,11 +769,13 @@ class AttributePool {
const AvailabilityChange &obsoleted,
SourceLocation unavailable, const Expr *MessageExpr,
ParsedAttr::Form form, SourceLocation strict,
- const Expr *ReplacementExpr) {
+ const Expr *ReplacementExpr,
+ IdentifierLoc *EnvironmentLoc) {
void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
- return add(new (memory) ParsedAttr(
- attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
- obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ Param, introduced, deprecated, obsoleted,
+ unavailable, MessageExpr, form, strict,
+ ReplacementExpr, EnvironmentLoc));
}
ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
@@ -993,10 +1005,12 @@ class ParsedAttributes : public ParsedAttributesView {
const AvailabilityChange &obsoleted,
SourceLocation unavailable, const Expr *MessageExpr,
ParsedAttr::Form form, SourceLocation strict,
- const Expr *ReplacementExpr) {
- ParsedAttr *attr = pool.create(
- attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
- obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr);
+ const Expr *ReplacementExpr,
+ IdentifierLoc *EnvironmentLoc) {
+ ParsedAttr *attr =
+ pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
+ deprecated, obsoleted, unavailable, MessageExpr, form,
+ strict, ReplacementExpr, EnvironmentLoc);
addAtEnd(attr);
return attr;
}
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1e89dfc58d92b..d2686e9f8bd79 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -39,6 +39,7 @@
#include "clang/Basic/Cuda.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/PragmaKinds.h"
@@ -3623,7 +3624,9 @@ class Sema final : public SemaBase {
VersionTuple Introduced, VersionTuple Deprecated,
VersionTuple Obsoleted, bool IsUnavailable,
StringRef Message, bool IsStrict, StringRef Replacement,
- AvailabilityMergeKind AMK, int Priority);
+ AvailabilityMergeKind AMK, int Priority,
+ IdentifierInfo *IIEnvironment);
+
TypeVisibilityAttr *
mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
TypeVisibilityAttr::VisibilityType Vis);
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 434926324c96c..87177d00c83a4 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -666,12 +666,27 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
// Make sure that this declaration has already been introduced.
if (!A->getIntroduced().empty() &&
EnclosingVersion < A->getIntroduced()) {
- if (Message) {
- Message->clear();
- llvm::raw_string_ostream Out(*Message);
- VersionTuple VTI(A->getIntroduced());
- Out << "introduced in " << PrettyPlatformName << ' '
- << VTI << HintMessage;
+ IdentifierInfo *IIEnv = A->getEnvironment();
+ StringRef TargetEnv = Context.getTargetInfo().getTriple().getEnvironmentName();
+ StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv);
+ // Matching environment or no environment on attribute
+ if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) {
+ if (Message) {
+ Message->clear();
+ llvm::raw_string_ostream Out(*Message);
+ VersionTuple VTI(A->getIntroduced());
+ Out << "introduced in " << PrettyPlatformName << " "
+ << VTI << EnvName << HintMessage;
+ }
+ }
+ // Non-matching environment or no environment on target
+ else {
+ if (Message) {
+ Message->clear();
+ llvm::raw_string_ostream Out(*Message);
+ Out << "not available on " << PrettyPlatformName << " "
+ << EnvName << HintMessage;
+ }
}
return A->getStrict() ? AR_Unavailable : AR_NotYetIntroduced;
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 06409c6fc7741..ca0582ef39a27 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -18,14 +18,19 @@ namespace hlsl {
#define _HLSL_BUILTIN_ALIAS(builtin) \
__attribute__((clang_builtin_alias(builtin)))
-#define _HLSL_AVAILABILITY(environment, version) \
- __attribute__((availability(environment, introduced = version)))
+#define _HLSL_AVAILABILITY(platform, version) \
+ __attribute__((availability(platform, introduced = version)))
+#define _HLSL_AVAILABILITY_STAGE(platform, version, stage) \
+ __attribute__((availability(platform, introduced = version, environment = stage)))
#ifdef __HLSL_ENABLE_16_BIT
-#define _HLSL_16BIT_AVAILABILITY(environment, version) \
- __attribute__((availability(environment, introduced = version)))
+#define _HLSL_16BIT_AVAILABILITY(platform, version) \
+ __attribute__((availability(platform, introduced = version)))
+#define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage) \
+ __attribute__((availability(platform, introduced = version, environment = stage)))
#else
#define _HLSL_16BIT_AVAILABILITY(environment, version)
+#define _HLSL_16BIT_AVAILABILITY_STAGE(environment, version, stage)
#endif
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Index/CommentToXML.cpp b/clang/lib/Index/CommentToXML.cpp
index 295f3f228ff79..5a484bdd15eaa 100644
--- a/clang/lib/Index/CommentToXML.cpp
+++ b/clang/lib/Index/CommentToXML.cpp
@@ -1052,6 +1052,9 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
}
if (AA->getUnavailable())
Result << "<Unavailable/>";
+
+ // HEKOTA TODO add Environment here
+
Result << "</Availability>";
}
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 5f26b5a9e46be..55facfb009932 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1224,6 +1224,7 @@ void Parser::ParseAvailabilityAttribute(
enum { Introduced, Deprecated, Obsoleted, Unknown };
AvailabilityChange Changes[Unknown];
ExprResult MessageExpr, ReplacementExpr;
+ IdentifierLoc *EnvironmentLoc = nullptr;
// Opening '('.
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1271,6 +1272,7 @@ void Parser::ParseAvailabilityAttribute(
Ident_message = PP.getIdentifierInfo("message");
Ident_strict = PP.getIdentifierInfo("strict");
Ident_replacement = PP.getIdentifierInfo("replacement");
+ Ident_environment = PP.getIdentifierInfo("environment");
}
// Parse the optional "strict", the optional "replacement" and the set of
@@ -1318,6 +1320,13 @@ void Parser::ParseAvailabilityAttribute(
continue;
}
+ if (Keyword == Ident_environment) {
+ if (EnvironmentLoc != nullptr) {
+ Diag(KeywordLoc, diag::err_availability_redundant)
+ << Keyword << SourceRange(EnvironmentLoc->Loc);
+ }
+ }
+
if (Tok.isNot(tok::equal)) {
Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;
SkipUntil(tok::r_paren, StopAtSemi);
@@ -1339,6 +1348,15 @@ void Parser::ParseAvailabilityAttribute(
continue;
}
}
+ if (Keyword == Ident_environment) {
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_availability_expected_environment);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ EnvironmentLoc = ParseIdentifierLoc();
+ continue;
+ }
// Special handling of 'NA' only when applied to introduced or
// deprecated.
@@ -1420,7 +1438,7 @@ void Parser::ParseAvailabilityAttribute(
SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName,
ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated],
Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), Form,
- StrictLoc, ReplacementExpr.get());
+ StrictLoc, ReplacementExpr.get(), EnvironmentLoc);
}
/// Parse the contents of the "external_source_symbol" attribute.
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 4c445f28bba8c..b904fa0b04448 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -268,7 +268,8 @@ static void ProcessAPINotes(Sema &S, Decl *D,
ASTAllocateString(S.Context, Info.UnavailableMsg),
/*Strict=*/false,
/*Replacement=*/StringRef(),
- /*Priority=*/Sema::AP_Explicit);
+ /*Priority=*/Sema::AP_Explicit,
+ /*Environment=*/nullptr);
},
[](const Decl *D) {
return llvm::find_if(D->attrs(), [](const Attr *next) -> bool {
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 846a31a796730..2a24cef17b469 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -14,19 +14,35 @@
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
+#include "llvm/ADT/StringRef.h"
#include <optional>
using namespace clang;
using namespace sema;
+static bool hasMatchingEnvironmentOrNone(const ASTContext &Context, const AvailabilityAttr *AA) {
+ IdentifierInfo *IIEnvironment = AA->getEnvironment();
+ auto Environment = Context.getTargetInfo().getTriple().getEnvironment();
+ if (!IIEnvironment || Environment == llvm::Triple::UnknownEnvironment)
+ return true;
+
+ llvm::Triple::EnvironmentType ET =
+ AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
+ return Environment == ET;
+}
+
static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
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)) {
// FIXME: this is copied from CheckAvailability. We should try to
@@ -45,11 +61,15 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
StringRef TargetPlatform = Context.getTargetInfo().getPlatformName();
// Match the platform name.
- if (RealizedPlatform == TargetPlatform)
- return Avail;
+ if (RealizedPlatform == TargetPlatform) {
+ // Find the best matching attribute for this environment
+ if (hasMatchingEnvironmentOrNone(Context, Avail))
+ return Avail;
+ PartialMatch = Avail;
+ }
}
}
- return nullptr;
+ return PartialMatch;
}
/// The diagnostic we should emit for \c D, and the declaration that
@@ -118,8 +138,9 @@ ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D,
/// the context of \c Ctx. For example, we should emit an unavailable diagnostic
/// in a deprecated context, but not the other way around.
static bool
-ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
- VersionTuple DeclVersion, Decl *Ctx,
+ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
+ VersionTuple DeclVersion,
+ const IdentifierInfo* DeclEnv, Decl *Ctx,
const NamedDecl *OffendingDecl) {
assert(K != AR_Available && "Expected an unavailable declaration here!");
@@ -139,7 +160,7 @@ ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
auto CheckContext = [&](const Decl *C) {
if (K == AR_NotYetIntroduced) {
if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C))
- if (AA->getIntroduced() >= DeclVersion)
+ if (AA->getIntroduced() >= DeclVersion && AA->getEnvironment() == DeclEnv )
return true;
} else if (K == AR_Deprecated) {
if (C->isDeprecated())
@@ -343,10 +364,14 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
unsigned available_here_select_kind;
VersionTuple DeclVersion;
- if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl))
+ const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl);
+ const IdentifierInfo *IIEnv = nullptr;
+ if (AA) {
DeclVersion = AA->getIntroduced();
+ IIEnv = AA->getEnvironment();
+ }
- if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx,
+ if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, IIEnv, Ctx,
OffendingDecl))
return;
@@ -354,8 +379,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
// The declaration can have multiple availability attributes, we are looking
// at one of them.
- const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
- if (A && A->isInherited()) {
+ if (AA && AA->isInherited()) {
for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl;
Redecl = Redecl->getPreviousDecl()) {
const AvailabilityAttr *AForRedecl =
@@ -375,9 +399,9 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
// not specified for deployment targets >= to iOS 11 or equivalent or
// for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
// later.
- const AvailabilityAttr *AA =
- getAttrForPlatform(S.getASTContext(), OffendingDecl);
+ assert(AA != nullptr && "expecting valid availability attribute");
VersionTuple Introduced = AA->getIntroduced();
+ bool EnvironmentMatches = hasMatchingEnvironmentOrNone(S.getASTContext(), AA);
bool UseNewWarning = shouldDiagnoseAvailabilityByDefault(
S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
@@ -385,16 +409,25 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new
: diag::warn_unguarded_availability;
- std::string PlatformName(AvailabilityAttr::getPrettyPlatformName(
- S.getASTContext().getTargetInfo().getPlatformName()));
+ const TargetInfo &TI = S.getASTContext().getTargetInfo();
+ std::string PlatformName(
+ AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
+ std::string TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
+ TI.getTriple().getEnvironmentName()));
+ VersionTuple UseVersion =
+ EnvironmentMatches ? Introduced : TI.getTriple().getOSVersion();
+ bool UseEnvironment =
+ (AA->getEnvironment() != nullptr && !TargetEnvironment.empty());
S.Diag(Loc, Warning) << OffendingDecl << PlatformName
- << Introduced.getAsString();
+ << UseVersion.getAsString() << UseEnvironment
+ << TargetEnvironment << !EnvironmentMatches;
- S.Diag(OffendingDecl->getLocation(),
- diag::note_partial_availability_specified_here)
- << OffendingDecl << PlatformName << Introduced.getAsString()
- << S.Context.getTargetInfo().getPlatformMinVersion().getAsString();
+ if (EnvironmentMatches)
+ S.Diag(OffendingDecl->getLocation(),
+ diag::note_partial_availability_specified_here)
+ << OffendingDecl << PlatformName << UseVersion.getAsString()
+ << S.Context.getTargetInfo().getPlatformMinVersion().getAsString();
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
@@ -771,17 +804,22 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
const AvailabilityAttr *AA =
getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
+ bool EnvironmentMatches =
+ hasMatchingEnvironmentOrNone(SemaRef.getASTContext(), AA);
VersionTuple Introduced = AA->getIntroduced();
- if (AvailabilityStack.back() >= Introduced)
+ if (EnvironmentMatches && AvailabilityStack.back() >= Introduced)
return;
// If the context of this function is less available than D, we should not
// emit a diagnostic.
- if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx,
+ if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced,
+ AA->getEnvironment(), Ctx,
OffendingDecl))
return;
+ // HEKOTA: use different error message when !environmentMatches ?
+ //
// 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
@@ -793,18 +831,27 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
? diag::warn_unguarded_availability_new
: diag::warn_unguarded_availability;
- std::string PlatformName(AvailabilityAttr::getPrettyPlatformName(
- SemaRef.getASTContext().getTargetInfo().getPlatformName()));
+ const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
+ std::string PlatformName(
+ AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
+ std::string TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
+ TI.getTriple().getEnvironmentName()));
+ VersionTuple UseVersion =
+ EnvironmentMatches ? Introduced : TI.getTriple().getOSVersion();
+ bool useEnvironment =
+ (AA->getEnvironment() != nullptr && !TargetEnvironment.empty());
SemaRef.Diag(Range.getBegin(), DiagKind)
- << Range << D << PlatformName << Introduced.getAsString();
-
- SemaRef.Diag(OffendingDecl->getLocation(),
- diag::note_partial_availability_specified_here)
- << OffendingDecl << PlatformName << Introduced.getAsString()
- << SemaRef.Context.getTargetInfo()
- .getPlatformMinVersion()
- .getAsString();
+ << Range << D << PlatformName << UseVersion.getAsString()
+ << useEnvironment << TargetEnvironment << !EnvironmentMatches;
+
+ if (EnvironmentMatches)
+ SemaRef.Diag(OffendingDecl->getLocation(),
+ diag::note_partial_availability_specified_here)
+ << OffendingDecl << PlatformName << Introduced.getAsString()
+ << SemaRef.Context.getTargetInfo()
+ .getPlatformMinVersion()
+ .getAsString();
auto FixitDiag =
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index af6b3f21f15a6..a9188e69f50ee 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2916,7 +2916,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
D, *AA, AA->getPlatform(), AA->isImplicit(), AA->getIntroduced(),
AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(),
AA->getMessage(), AA->getStrict(), AA->getReplacement(), AMK,
- AA->getPriority());
+ AA->getPriority(), AA->getEnvironment());
else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr))
NewAttr = S.mergeVisibilityAttr(D, *VA, VA->getVisibility());
else if (const auto *VA = dyn_cast<TypeVisibilityAttr>(Attr))
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 363ae93cb62df..b8f704155f793 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -26,6 +26,7 @@
#include "clang/Basic/Cuda.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/HLSLRuntime.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
@@ -51,6 +52,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
#include <optional>
using namespace clang;
@@ -2494,7 +2496,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(
bool Implicit, VersionTuple Introduced, VersionTuple Deprecated,
VersionTuple Obsoleted, bool IsUnavailable, StringRef Message,
bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK,
- int Priority) {
+ int Priority, IdentifierInfo *Environment) {
VersionTuple MergedIntroduced = Introduced;
VersionTuple MergedDeprecated = Deprecated;
VersionTuple MergedObsoleted = Obsoleted;
@@ -2528,6 +2530,12 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(
continue;
}
+ IdentifierInfo *OldEnvironment = OldAA->getEnvironment();
+ if (OldEnvironment != Environment) {
+ ++i;
+ continue;
+ }
+
// If there is an existing availability attribute for this platform that
// has a lower priority use the existing one and discard the new
// attribute.
@@ -2646,7 +2654,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(
!OverrideOrImpl) {
auto *Avail = ::new (Context) AvailabilityAttr(
Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable,
- Message, IsStrict, Replacement, Priority);
+ Message, IsStrict, Replacement, Priority, Environment);
Avail->setImplicit(Implicit);
return Avail;
}
@@ -2708,10 +2716,22 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
int PriorityModifier = AL.isPragmaClangAttribute()
? Sema::AP_PragmaClangAttribute
: Sema::AP_Explicit;
+
+ const IdentifierLoc *EnvironmentLoc = AL.getEnvironment();
+ IdentifierInfo *IIEnvironment = nullptr;
+ if (EnvironmentLoc) {
+ IIEnvironment = EnvironmentLoc->Ident;
+ if (AvailabilityAttr::getEnvironmentType(
+ EnvironmentLoc->Ident->getName()) ==
+ llvm::Triple::EnvironmentType::UnknownEnvironment)
+ S.Diag(Platform->Loc, diag::warn_availability_unknown_environment)
+ << EnvironmentLoc->Ident;
+ }
+
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version,
Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement,
- Sema::AMK_None, PriorityModifier);
+ Sema::AMK_None, PriorityModifier, IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
@@ -2768,7 +2788,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform);
+ PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -2810,7 +2830,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform);
+ PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -2843,7 +2863,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
MinMacCatalystVersion(Deprecated.Version),
MinMacCatalystVersion(Obsoleted.Version), IsUnavailable, Str,
IsStrict, Replacement, Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform);
+ PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
} else if (II->getName() == "macos" && GetSDKInfo() &&
@@ -2886,7 +2906,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str,
IsStrict, Replacement, Sema::AMK_None,
PriorityModifier + Sema::AP_InferredFromOtherPlatform +
- Sema::AP_InferredFromOtherPlatform);
+ Sema::AP_InferredFromOtherPlatform, IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
>From 36eb95468b95e3dd545f0eb7eb3eddfeb68db97e Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 23 Apr 2024 13:20:19 -0700
Subject: [PATCH 2/8] apply clang-format
---
clang/include/clang/Sema/ParsedAttr.h | 8 +++----
clang/include/clang/Sema/Sema.h | 16 ++++++--------
clang/lib/AST/DeclBase.cpp | 11 +++++-----
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 14 ++++++------
clang/lib/Index/CommentToXML.cpp | 2 +-
clang/lib/Sema/SemaAvailability.cpp | 27 ++++++++++++------------
clang/lib/Sema/SemaDeclAttr.cpp | 11 +++++-----
7 files changed, 46 insertions(+), 43 deletions(-)
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 7ad39d1a4942f..a2b35e71795cd 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -73,10 +73,10 @@ struct AvailabilityData {
AvailabilityData(const AvailabilityChange &Introduced,
const AvailabilityChange &Deprecated,
- const AvailabilityChange &Obsoleted,
- SourceLocation Strict, const Expr *ReplaceExpr,
- const IdentifierLoc *EnvironmentLoc)
- : StrictLoc(Strict), Replacement(ReplaceExpr), EnvironmentLoc(EnvironmentLoc) {
+ const AvailabilityChange &Obsoleted, SourceLocation Strict,
+ const Expr *ReplaceExpr, const IdentifierLoc *EnvironmentLoc)
+ : StrictLoc(Strict), Replacement(ReplaceExpr),
+ EnvironmentLoc(EnvironmentLoc) {
Changes[IntroducedSlot] = Introduced;
Changes[DeprecatedSlot] = Deprecated;
Changes[ObsoletedSlot] = Obsoleted;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f84c023d6f78e..64b06b42f17ab 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3619,15 +3619,13 @@ class Sema final : public SemaBase {
bool CheckAttrTarget(const ParsedAttr &CurrAttr);
bool CheckAttrNoArgs(const ParsedAttr &CurrAttr);
- AvailabilityAttr *
- mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI,
- IdentifierInfo *Platform, bool Implicit,
- VersionTuple Introduced, VersionTuple Deprecated,
- VersionTuple Obsoleted, bool IsUnavailable,
- StringRef Message, bool IsStrict, StringRef Replacement,
- AvailabilityMergeKind AMK, int Priority,
- IdentifierInfo *IIEnvironment);
-
+ AvailabilityAttr *mergeAvailabilityAttr(
+ NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform,
+ bool Implicit, VersionTuple Introduced, VersionTuple Deprecated,
+ VersionTuple Obsoleted, bool IsUnavailable, StringRef Message,
+ bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK,
+ int Priority, IdentifierInfo *IIEnvironment);
+
TypeVisibilityAttr *
mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
TypeVisibilityAttr::VisibilityType Vis);
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index fbb7f2b3ac30a..9b9e49ec7f761 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -667,7 +667,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
if (!A->getIntroduced().empty() &&
EnclosingVersion < A->getIntroduced()) {
IdentifierInfo *IIEnv = A->getEnvironment();
- StringRef TargetEnv = Context.getTargetInfo().getTriple().getEnvironmentName();
+ StringRef TargetEnv =
+ Context.getTargetInfo().getTriple().getEnvironmentName();
StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv);
// Matching environment or no environment on attribute
if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) {
@@ -675,8 +676,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTI(A->getIntroduced());
- Out << "introduced in " << PrettyPlatformName << " "
- << VTI << EnvName << HintMessage;
+ Out << "introduced in " << PrettyPlatformName << " " << VTI << EnvName
+ << HintMessage;
}
}
// Non-matching environment or no environment on target
@@ -684,8 +685,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
- Out << "not available on " << PrettyPlatformName << " "
- << EnvName << HintMessage;
+ Out << "not available on " << PrettyPlatformName << " " << EnvName
+ << HintMessage;
}
}
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index ca0582ef39a27..6880e26600d0b 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -18,16 +18,18 @@ namespace hlsl {
#define _HLSL_BUILTIN_ALIAS(builtin) \
__attribute__((clang_builtin_alias(builtin)))
-#define _HLSL_AVAILABILITY(platform, version) \
+#define _HLSL_AVAILABILITY(platform, version) \
__attribute__((availability(platform, introduced = version)))
-#define _HLSL_AVAILABILITY_STAGE(platform, version, stage) \
- __attribute__((availability(platform, introduced = version, environment = stage)))
+#define _HLSL_AVAILABILITY_STAGE(platform, version, stage) \
+ __attribute__(( \
+ availability(platform, introduced = version, environment = stage)))
#ifdef __HLSL_ENABLE_16_BIT
-#define _HLSL_16BIT_AVAILABILITY(platform, version) \
+#define _HLSL_16BIT_AVAILABILITY(platform, version) \
__attribute__((availability(platform, introduced = version)))
-#define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage) \
- __attribute__((availability(platform, introduced = version, environment = stage)))
+#define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage) \
+ __attribute__(( \
+ availability(platform, introduced = version, environment = stage)))
#else
#define _HLSL_16BIT_AVAILABILITY(environment, version)
#define _HLSL_16BIT_AVAILABILITY_STAGE(environment, version, stage)
diff --git a/clang/lib/Index/CommentToXML.cpp b/clang/lib/Index/CommentToXML.cpp
index 5a484bdd15eaa..498476063f062 100644
--- a/clang/lib/Index/CommentToXML.cpp
+++ b/clang/lib/Index/CommentToXML.cpp
@@ -1054,7 +1054,7 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
Result << "<Unavailable/>";
// HEKOTA TODO add Environment here
-
+
Result << "</Availability>";
}
}
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 2a24cef17b469..c6b2ec6fa59be 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -26,17 +26,18 @@
using namespace clang;
using namespace sema;
-static bool hasMatchingEnvironmentOrNone(const ASTContext &Context, const AvailabilityAttr *AA) {
+static bool hasMatchingEnvironmentOrNone(const ASTContext &Context,
+ const AvailabilityAttr *AA) {
IdentifierInfo *IIEnvironment = AA->getEnvironment();
auto Environment = Context.getTargetInfo().getTriple().getEnvironment();
- if (!IIEnvironment || Environment == llvm::Triple::UnknownEnvironment)
+ if (!IIEnvironment || Environment == llvm::Triple::UnknownEnvironment)
return true;
-
+
llvm::Triple::EnvironmentType ET =
AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());
return Environment == ET;
}
-
+
static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
const Decl *D) {
AvailabilityAttr const *PartialMatch = nullptr;
@@ -137,11 +138,9 @@ ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D,
/// whether we should emit a diagnostic for \c K and \c DeclVersion in
/// the context of \c Ctx. For example, we should emit an unavailable diagnostic
/// in a deprecated context, but not the other way around.
-static bool
-ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
- VersionTuple DeclVersion,
- const IdentifierInfo* DeclEnv, Decl *Ctx,
- const NamedDecl *OffendingDecl) {
+static bool ShouldDiagnoseAvailabilityInContext(
+ Sema &S, AvailabilityResult K, VersionTuple DeclVersion,
+ const IdentifierInfo *DeclEnv, Decl *Ctx, const NamedDecl *OffendingDecl) {
assert(K != AR_Available && "Expected an unavailable declaration here!");
// If this was defined using CF_OPTIONS, etc. then ignore the diagnostic.
@@ -160,7 +159,8 @@ ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K,
auto CheckContext = [&](const Decl *C) {
if (K == AR_NotYetIntroduced) {
if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C))
- if (AA->getIntroduced() >= DeclVersion && AA->getEnvironment() == DeclEnv )
+ if (AA->getIntroduced() >= DeclVersion &&
+ AA->getEnvironment() == DeclEnv)
return true;
} else if (K == AR_Deprecated) {
if (C->isDeprecated())
@@ -401,7 +401,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
// later.
assert(AA != nullptr && "expecting valid availability attribute");
VersionTuple Introduced = AA->getIntroduced();
- bool EnvironmentMatches = hasMatchingEnvironmentOrNone(S.getASTContext(), AA);
+ bool EnvironmentMatches =
+ hasMatchingEnvironmentOrNone(S.getASTContext(), AA);
bool UseNewWarning = shouldDiagnoseAvailabilityByDefault(
S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
@@ -813,13 +814,13 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
// If the context of this function is less available than D, we should not
// emit a diagnostic.
- if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced,
+ if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced,
AA->getEnvironment(), Ctx,
OffendingDecl))
return;
// HEKOTA: use different error message when !environmentMatches ?
- //
+ //
// 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
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b8f704155f793..8a8e297261678 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2787,8 +2787,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
- Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment);
+ Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform,
+ IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -2829,8 +2829,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
- Sema::AMK_None,
- PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment);
+ Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform,
+ IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
@@ -2906,7 +2906,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str,
IsStrict, Replacement, Sema::AMK_None,
PriorityModifier + Sema::AP_InferredFromOtherPlatform +
- Sema::AP_InferredFromOtherPlatform, IIEnvironment);
+ Sema::AP_InferredFromOtherPlatform,
+ IIEnvironment);
if (NewAttr)
D->addAttr(NewAttr);
}
>From 0a66eb21674bfd68d70ce0424d77f17c7e4cce58 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 25 Apr 2024 16:57:32 -0700
Subject: [PATCH 3/8] Add tests and documentation, adjust diag messages
---
clang/include/clang/Basic/Attr.td | 2 +-
clang/include/clang/Basic/AttrDocs.td | 5 ++-
.../clang/Basic/DiagnosticParseKinds.td | 2 +-
.../clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/lib/Index/CommentToXML.cpp | 7 ++-
clang/lib/Sema/SemaAvailability.cpp | 12 ++---
clang/test/Parser/attr-availability.c | 4 ++
clang/test/SemaHLSL/AvailabilityMarkup.hlsl | 8 ++--
.../SemaHLSL/AvailabilityMarkupStages.hlsl | 44 +++++++++++++++++++
.../SemaHLSL/WaveBuiltinAvailability.hlsl | 4 +-
10 files changed, 72 insertions(+), 18 deletions(-)
create mode 100644 clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index fb5b6d466c6ff..251a2cf04e37d 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -976,7 +976,7 @@ def Availability : InheritableAttr {
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOS (App Extension)")
.Case("swift", "Swift")
- .Case("shadermodel", "HLSL Shader Model")
+ .Case("shadermodel", "Shader Model")
.Case("ohos", "OpenHarmony OS")
.Default(llvm::StringRef());
}
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index a81163df35ca8..9c2f3f9e833a5 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1593,7 +1593,10 @@ replacement=\ *string-literal*
a warning about use of a deprecated declaration. The Fix-It will replace
the deprecated declaration with the new declaration specified.
-// HEKOTA TODO add docs here
+environment=\ *identifier*
+ Target environment in which this declaration is available. If present,
+ the availability attribute applies only to targets with the same platform
+ and environment.
Multiple availability attributes can be placed on a declaration, which may
correspond to different platforms. For most platforms, the availability
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 624e7b0ecf272..31309b8cd7067 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1104,7 +1104,7 @@ def err_zero_version : Error<
def err_availability_expected_platform : Error<
"expected a platform name, e.g., 'macos'">;
def err_availability_expected_environment : Error<
- "expected an environment name, e.g., 'pixel'">;
+ "expected an environment name, e.g., 'compute'">;
// objc_bridge_related attribute
def err_objcbridge_related_expected_related_class : Error<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8ac94349d79aa..f3a9f1b90db59 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5860,7 +5860,7 @@ def note_availability_specified_here : Note<
"%0 has been explicitly marked "
"%select{unavailable|deleted|deprecated}1 here">;
def note_partial_availability_specified_here : Note<
- "%0 has been marked as being introduced in %1 %2 here, "
+ "%0 has been marked as being introduced in %1 %2 %select{|in %5 environment }4here, "
"but the deployment target is %1 %3">;
def note_implicitly_deleted : Note<
"explicitly defaulted function was implicitly deleted here">;
diff --git a/clang/lib/Index/CommentToXML.cpp b/clang/lib/Index/CommentToXML.cpp
index 498476063f062..3372fbba43831 100644
--- a/clang/lib/Index/CommentToXML.cpp
+++ b/clang/lib/Index/CommentToXML.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/Comment.h"
#include "clang/AST/CommentVisitor.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Index/USRGeneration.h"
@@ -1053,8 +1054,10 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
if (AA->getUnavailable())
Result << "<Unavailable/>";
- // HEKOTA TODO add Environment here
-
+ IdentifierInfo *Environment = AA->getEnvironment();
+ if (Environment) {
+ Result << "<Environment>" << Environment->getName() << "</Environment>";
+ }
Result << "</Availability>";
}
}
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index c6b2ec6fa59be..e0d3383bdfca9 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -428,7 +428,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
S.Diag(OffendingDecl->getLocation(),
diag::note_partial_availability_specified_here)
<< OffendingDecl << PlatformName << UseVersion.getAsString()
- << S.Context.getTargetInfo().getPlatformMinVersion().getAsString();
+ << S.Context.getTargetInfo().getPlatformMinVersion().getAsString()
+ << UseEnvironment << TargetEnvironment;
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
@@ -819,8 +820,6 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
OffendingDecl))
return;
- // HEKOTA: use different error message when !environmentMatches ?
- //
// 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
@@ -839,12 +838,12 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
TI.getTriple().getEnvironmentName()));
VersionTuple UseVersion =
EnvironmentMatches ? Introduced : TI.getTriple().getOSVersion();
- bool useEnvironment =
+ bool UseEnvironment =
(AA->getEnvironment() != nullptr && !TargetEnvironment.empty());
SemaRef.Diag(Range.getBegin(), DiagKind)
<< Range << D << PlatformName << UseVersion.getAsString()
- << useEnvironment << TargetEnvironment << !EnvironmentMatches;
+ << UseEnvironment << TargetEnvironment << !EnvironmentMatches;
if (EnvironmentMatches)
SemaRef.Diag(OffendingDecl->getLocation(),
@@ -852,7 +851,8 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
<< OffendingDecl << PlatformName << Introduced.getAsString()
<< SemaRef.Context.getTargetInfo()
.getPlatformMinVersion()
- .getAsString();
+ .getAsString()
+ << UseEnvironment << TargetEnvironment;
auto FixitDiag =
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
diff --git a/clang/test/Parser/attr-availability.c b/clang/test/Parser/attr-availability.c
index aab0f2f3a852a..8ba120f944a73 100644
--- a/clang/test/Parser/attr-availability.c
+++ b/clang/test/Parser/attr-availability.c
@@ -30,6 +30,10 @@ void f11(void) __attribute__((availability(macosx,message=u"b"))); // expected-w
void f12(void) __attribute__((availability(macosx,message="a" u"b"))); // expected-warning {{encoding prefix 'u' on an unevaluated string literal has no effect}}
+void f13(void) __attribute__((availability(shadermodel, introduced = 6.0, environment="pixel"))); // expected-error {{expected an environment name, e.g., 'compute'}}
+
+void f14(void) __attribute__((availability(shadermodel, introduced = 6.0, environment=pixel, environment=compute))); // expected-error {{redundant 'environment' availability change; only the last specified change will be used}}
+
enum E{
gorf __attribute__((availability(macosx,introduced=8.5, message = 10.0))), // expected-error {{expected string literal for optional message in 'availability' attribute}}
garf __attribute__((availability(macosx,introduced=8.5, message))), // expected-error {{expected '=' after 'message'}}
diff --git a/clang/test/SemaHLSL/AvailabilityMarkup.hlsl b/clang/test/SemaHLSL/AvailabilityMarkup.hlsl
index b883957af0871..ece5ca9d3ea9f 100644
--- a/clang/test/SemaHLSL/AvailabilityMarkup.hlsl
+++ b/clang/test/SemaHLSL/AvailabilityMarkup.hlsl
@@ -10,13 +10,13 @@ __attribute__((availability(shadermodel, introduced = 5.0)))
unsigned fn5_0();
void fn() {
- // expected-warning@#fn6_0_site {{'fn6_0' is only available on HLSL ShaderModel 6.0 or newer}}
- // expected-note@#fn6_0 {{'fn6_0' has been marked as being introduced in HLSL ShaderModel 6.0 here, but the deployment target is HLSL ShaderModel 5.0}}
+ // expected-warning@#fn6_0_site {{'fn6_0' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0 {{'fn6_0' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
// expected-note@#fn6_0_site {{enclose 'fn6_0' in a __builtin_available check to silence this warning}}
unsigned A = fn6_0(); // #fn6_0_site
- // expected-warning@#fn5_1_site {{'fn5_1' is only available on HLSL ShaderModel 5.1 or newer}}
- // expected-note@#fn5_1 {{'fn5_1' has been marked as being introduced in HLSL ShaderModel 5.1 here, but the deployment target is HLSL ShaderModel 5.0}}
+ // expected-warning@#fn5_1_site {{'fn5_1' is only available on Shader Model 5.1 or newer}}
+ // expected-note@#fn5_1 {{'fn5_1' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
// expected-note@#fn5_1_site {{enclose 'fn5_1' in a __builtin_available check to silence this warning}}
unsigned B = fn5_1(); // #fn5_1_site
diff --git a/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl b/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
new file mode 100644
index 0000000000000..ae3c260242339
--- /dev/null
+++ b/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple dxil-unknown-shadermodel5.0-compute -verify %s
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned fn6_0_all(); // #fn6_0_all_def
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned fn5_0_all();
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
+unsigned fn6_0_stages1(); // #fn6_0_stages1_def
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned fn6_0_stages2(); // #fn6_0_stages2_def
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned fn5_0_stages();
+
+void fn() {
+
+ // expected-warning@#fn6_0_all_call {{'fn6_0_all' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0_all_def {{'fn6_0_all' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ // expected-note@#fn6_0_all_call {{enclose 'fn6_0_all' in a __builtin_available check to silence this warning}}
+ unsigned A = fn6_0_all(); // #fn6_0_all_call
+
+ unsigned B = fn5_0_all();
+
+ // expected-warning@#fn6_0_stages1_call {{'fn6_0_stages1' is only available in compute shader environment on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0_stages1_def {{'fn6_0_stages1' 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@#fn6_0_stages1_call {{enclose 'fn6_0_stages1' in a __builtin_available check to silence this warning}}
+ unsigned C = fn6_0_stages1(); // #fn6_0_stages1_call
+
+ // expected-warning@#fn6_0_stages2_call {{'fn6_0_stages2' is not available in compute shader environment on Shader Model 5.0}}
+ // expected-note@#fn6_0_stages2_call {{enclose 'fn6_0_stages2' in a __builtin_available check to silence this warning}}
+ unsigned E = fn6_0_stages2(); // #fn6_0_stages2_call
+
+ unsigned D = fn5_0_stages();
+}
diff --git a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
index 0e45edc6a4c86..185b79be37be5 100644
--- a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
+++ b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
@@ -2,8 +2,8 @@
// WaveActiveCountBits is unavailable before ShaderModel 6.0.
unsigned foo(bool b) {
- // expected-warning@#site {{'WaveActiveCountBits' is only available on HLSL ShaderModel 6.0 or newer}}
- // expected-note at hlsl/hlsl_intrinsics.h:* {{'WaveActiveCountBits' has been marked as being introduced in HLSL ShaderModel 6.0 here, but the deployment target is HLSL ShaderModel 5.0}}
+ // expected-warning@#site {{'WaveActiveCountBits' is only available on Shader Model 6.0 or newer}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{'WaveActiveCountBits' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
// expected-note@#site {{enclose 'WaveActiveCountBits' in a __builtin_available check to silence this warning}}
return hlsl::WaveActiveCountBits(b); // #site
}
>From eac0b91459cb2bcac0fc0e071bb1294171e2af14 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 30 Apr 2024 12:52:27 -0700
Subject: [PATCH 4/8] Remove trailing whitespace
---
clang/include/clang/Basic/AttrDocs.td | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 9c2f3f9e833a5..dbadaee7e0c4e 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1594,9 +1594,9 @@ replacement=\ *string-literal*
the deprecated declaration with the new declaration specified.
environment=\ *identifier*
- Target environment in which this declaration is available. If present,
+ Target environment in which this declaration is available. If present,
the availability attribute applies only to targets with the same platform
- and environment.
+ and environment.
Multiple availability attributes can be placed on a declaration, which may
correspond to different platforms. For most platforms, the availability
>From 65052906a9e01b80cc4cfba8b89d6e45ecc29537 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 7 May 2024 15:55:11 -0700
Subject: [PATCH 5/8] Modify diagnostic message when function is not available
for target environment for any version
---
.../clang/Basic/DiagnosticSemaKinds.td | 10 +-
clang/lib/Sema/SemaAvailability.cpp | 98 +++++++++++--------
.../SemaHLSL/AvailabilityMarkupStages.hlsl | 3 +-
3 files changed, 66 insertions(+), 45 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bd45b38364bb6..35210fea07b1a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3862,11 +3862,17 @@ def warn_availability_fuchsia_unavailable_minor : Warning<
InGroup<Availability>;
def warn_unguarded_availability :
- Warning<"%0 %select{is only|is not}5 available %select{|in %4 environment }3on %1 %2 %select{or newer|}5">,
+ Warning<"%0 is only available %select{|in %4 environment }3on %1 %2 or newer">,
+ InGroup<UnguardedAvailability>, DefaultIgnore;
+def warn_unguarded_availability_unavailable :
+ Warning<"%0 is unavailable">,
InGroup<UnguardedAvailability>, DefaultIgnore;
def warn_unguarded_availability_new :
Warning<warn_unguarded_availability.Summary>,
InGroup<UnguardedAvailabilityNew>;
+def warn_unguarded_availability_unavailable_new :
+ Warning<warn_unguarded_availability_unavailable.Summary>,
+ InGroup<UnguardedAvailabilityNew>;
def note_decl_unguarded_availability_silence : Note<
"annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">;
def note_unguarded_available_silence : Note<
@@ -5859,7 +5865,7 @@ def note_availability_specified_here : Note<
"%select{unavailable|deleted|deprecated}1 here">;
def note_partial_availability_specified_here : Note<
"%0 has been marked as being introduced in %1 %2 %select{|in %5 environment }4here, "
- "but the deployment target is %1 %3">;
+ "but the deployment target is %1 %3%select{| %6 environment }4">;
def note_implicitly_deleted : Note<
"explicitly defaulted function was implicitly deleted here">;
def warn_not_enough_argument : Warning<
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index e0d3383bdfca9..fb2e4f48d93e6 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -401,35 +401,44 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
// later.
assert(AA != nullptr && "expecting valid availability attribute");
VersionTuple Introduced = AA->getIntroduced();
- bool EnvironmentMatches =
+ bool EnvironmentMatchesOrNone =
hasMatchingEnvironmentOrNone(S.getASTContext(), AA);
- bool UseNewWarning = shouldDiagnoseAvailabilityByDefault(
- S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
- Introduced);
- unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new
- : diag::warn_unguarded_availability;
-
const TargetInfo &TI = S.getASTContext().getTargetInfo();
std::string PlatformName(
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
- std::string TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
+ llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
TI.getTriple().getEnvironmentName()));
- VersionTuple UseVersion =
- EnvironmentMatches ? Introduced : TI.getTriple().getOSVersion();
+ llvm::StringRef AttrEnvironment =
+ AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName(
+ AA->getEnvironment()->getName())
+ : "";
bool UseEnvironment =
- (AA->getEnvironment() != nullptr && !TargetEnvironment.empty());
+ (!AttrEnvironment.empty() && !TargetEnvironment.empty());
+
+ bool UseNewWarning = shouldDiagnoseAvailabilityByDefault(
+ S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
+ Introduced);
- S.Diag(Loc, Warning) << OffendingDecl << PlatformName
- << UseVersion.getAsString() << UseEnvironment
- << TargetEnvironment << !EnvironmentMatches;
+ if (EnvironmentMatchesOrNone) {
+ unsigned DiagKind = UseNewWarning ? diag::warn_unguarded_availability_new
+ : diag::warn_unguarded_availability;
- if (EnvironmentMatches)
- S.Diag(OffendingDecl->getLocation(),
- diag::note_partial_availability_specified_here)
- << OffendingDecl << PlatformName << UseVersion.getAsString()
- << S.Context.getTargetInfo().getPlatformMinVersion().getAsString()
+ S.Diag(Loc, DiagKind)
+ << OffendingDecl << PlatformName << Introduced.getAsString()
<< UseEnvironment << TargetEnvironment;
+ } else {
+ unsigned DiagKind =
+ UseNewWarning ? diag::warn_unguarded_availability_unavailable_new
+ : diag::warn_unguarded_availability_unavailable;
+ S.Diag(Loc, DiagKind) << Loc << OffendingDecl;
+ }
+
+ S.Diag(OffendingDecl->getLocation(),
+ diag::note_partial_availability_specified_here)
+ << OffendingDecl << PlatformName << Introduced.getAsString()
+ << S.Context.getTargetInfo().getPlatformMinVersion().getAsString()
+ << UseEnvironment << AttrEnvironment << TargetEnvironment;
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
@@ -806,11 +815,11 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
const AvailabilityAttr *AA =
getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
- bool EnvironmentMatches =
+ bool EnvironmentMatchesOrNone =
hasMatchingEnvironmentOrNone(SemaRef.getASTContext(), AA);
VersionTuple Introduced = AA->getIntroduced();
- if (EnvironmentMatches && AvailabilityStack.back() >= Introduced)
+ if (EnvironmentMatchesOrNone && AvailabilityStack.back() >= Introduced)
return;
// If the context of this function is less available than D, we should not
@@ -824,35 +833,40 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
// not specified for deployment targets >= to iOS 11 or equivalent or
// for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
// later.
- unsigned DiagKind =
- shouldDiagnoseAvailabilityByDefault(
- SemaRef.Context,
- SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced)
- ? diag::warn_unguarded_availability_new
- : diag::warn_unguarded_availability;
+ bool UseNewDiagKind = shouldDiagnoseAvailabilityByDefault(
+ SemaRef.Context,
+ SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced);
const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();
std::string PlatformName(
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
- std::string TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
+ llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
TI.getTriple().getEnvironmentName()));
- VersionTuple UseVersion =
- EnvironmentMatches ? Introduced : TI.getTriple().getOSVersion();
+ llvm::StringRef AttrEnvironment =
+ AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName(
+ AA->getEnvironment()->getName())
+ : "";
bool UseEnvironment =
- (AA->getEnvironment() != nullptr && !TargetEnvironment.empty());
-
- SemaRef.Diag(Range.getBegin(), DiagKind)
- << Range << D << PlatformName << UseVersion.getAsString()
- << UseEnvironment << TargetEnvironment << !EnvironmentMatches;
+ (!AttrEnvironment.empty() && !TargetEnvironment.empty());
- if (EnvironmentMatches)
- SemaRef.Diag(OffendingDecl->getLocation(),
- diag::note_partial_availability_specified_here)
- << OffendingDecl << PlatformName << Introduced.getAsString()
- << SemaRef.Context.getTargetInfo()
- .getPlatformMinVersion()
- .getAsString()
+ if (EnvironmentMatchesOrNone) {
+ unsigned DiagKind = UseNewDiagKind ? diag::warn_unguarded_availability_new
+ : diag::warn_unguarded_availability;
+ SemaRef.Diag(Range.getBegin(), DiagKind)
+ << Range << D << PlatformName << Introduced.getAsString()
<< UseEnvironment << TargetEnvironment;
+ } else {
+ unsigned DiagKind =
+ UseNewDiagKind ? diag::warn_unguarded_availability_unavailable_new
+ : diag::warn_unguarded_availability_unavailable;
+ SemaRef.Diag(Range.getBegin(), DiagKind) << Range << D;
+ }
+
+ SemaRef.Diag(OffendingDecl->getLocation(),
+ diag::note_partial_availability_specified_here)
+ << OffendingDecl << PlatformName << Introduced.getAsString()
+ << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
+ << UseEnvironment << AttrEnvironment << TargetEnvironment;
auto FixitDiag =
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
diff --git a/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl b/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
index ae3c260242339..3572cd85dd4ef 100644
--- a/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
+++ b/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
@@ -36,7 +36,8 @@ void fn() {
// expected-note@#fn6_0_stages1_call {{enclose 'fn6_0_stages1' in a __builtin_available check to silence this warning}}
unsigned C = fn6_0_stages1(); // #fn6_0_stages1_call
- // expected-warning@#fn6_0_stages2_call {{'fn6_0_stages2' is not available in compute shader environment on Shader Model 5.0}}
+ // expected-warning@#fn6_0_stages2_call {{'fn6_0_stages2' is unavailable}}
+ // expected-note@#fn6_0_stages2_def {{'fn6_0_stages2' 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@#fn6_0_stages2_call {{enclose 'fn6_0_stages2' in a __builtin_available check to silence this warning}}
unsigned E = fn6_0_stages2(); // #fn6_0_stages2_call
>From 22d2d24c927a867a3a9a93c1f754b61a9baa299e Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 8 May 2024 14:26:13 -0700
Subject: [PATCH 6/8] Move tests into Sema, add coverage for strict flag
- merge AvailabilityMarkup.hlsl and AvailabilityMarkupStages.hlsl into attr-availability-shadermodel.hlsl and move to Sema test directory
- add coverage for strict mode which uses different code path to generate the warnings
- add missing space in diag message
---
clang/lib/AST/DeclBase.cpp | 4 +-
.../Sema/attr-availability-shadermodel.hlsl | 139 ++++++++++++++++++
clang/test/SemaHLSL/AvailabilityMarkup.hlsl | 25 ----
.../SemaHLSL/AvailabilityMarkupStages.hlsl | 45 ------
4 files changed, 141 insertions(+), 72 deletions(-)
create mode 100644 clang/test/Sema/attr-availability-shadermodel.hlsl
delete mode 100644 clang/test/SemaHLSL/AvailabilityMarkup.hlsl
delete mode 100644 clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index f769c9ac277a7..65d5eeb6354eb 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -676,8 +676,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
VersionTuple VTI(A->getIntroduced());
- Out << "introduced in " << PrettyPlatformName << " " << VTI << EnvName
- << HintMessage;
+ Out << "introduced in " << PrettyPlatformName << " " << VTI << " "
+ << EnvName << HintMessage;
}
}
// Non-matching environment or no environment on target
diff --git a/clang/test/Sema/attr-availability-shadermodel.hlsl b/clang/test/Sema/attr-availability-shadermodel.hlsl
new file mode 100644
index 0000000000000..ef896e99a3c66
--- /dev/null
+++ b/clang/test/Sema/attr-availability-shadermodel.hlsl
@@ -0,0 +1,139 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-compute -fsyntax-only -verify %s
+
+// Platform shader model, no environment parameter
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned fn6_0(); // #fn6_0
+
+__attribute__((availability(shadermodel, introduced = 5.1)))
+unsigned fn5_1(); // #fn5_1
+
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned fn5_0();
+
+// Platform shader model, no environment parameter
+// - with strict flag (executes different code path)
+__attribute__((availability(shadermodel, strict, introduced = 6.0)))
+unsigned fn6_0_s(); // #fn6_0_s
+
+__attribute__((availability(shadermodel, strict, introduced = 5.1)))
+unsigned fn5_1_s(); // #fn5_1_s
+
+__attribute__((availability(shadermodel, strict, introduced = 5.0)))
+unsigned fn5_0_s();
+
+// Platform shader model, environment parameter restricting earlier version,
+// available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0)))
+unsigned fn6_0_mix(); // #fn6_0_mix
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0)))
+unsigned fn5_0_mix();
+
+// Platform shader model, environment parameter restricting earlier version,
+// available in all environments in higher versions
+// - with strict flag (executes different code path)
+__attribute__((availability(shadermodel, strict, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, strict, introduced = 6.0)))
+unsigned fn6_0_mix_s(); // #fn6_0_mix_s
+
+__attribute__((availability(shadermodel, strict, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, strict, introduced = 5.0)))
+unsigned fn5_0_mix_s();
+
+// Platform shader model, environment parameter restricting earlier version,
+// never available in all environments in higher versions
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
+unsigned fn6_0_stages1(); // #fn6_0_stages1
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned fn6_0_stages2(); // #fn6_0_stages2
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned fn5_0_stages();
+
+// Platform shader model, environment parameter restricting earlier version,
+// never available in all environments in higher versions
+// - with strict flag (executes different code path)
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
+unsigned fn6_0_stages1_s(); // #fn6_0_stages1_s
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned fn6_0_stages2_s(); // #fn6_0_stages2_s
+
+__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
+__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
+__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
+unsigned fn5_0_stages_s();
+
+int main() {
+ // expected-warning@#fn6_0_call {{'fn6_0' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0 {{'fn6_0' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ // expected-note@#fn6_0_call {{enclose 'fn6_0' in a __builtin_available check to silence this warning}}
+ unsigned A1 = fn6_0(); // #fn6_0_call
+
+ // expected-warning@#fn5_1_call {{'fn5_1' is only available on Shader Model 5.1 or newer}}
+ // expected-note@#fn5_1 {{'fn5_1' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
+ // expected-note@#fn5_1_call {{enclose 'fn5_1' in a __builtin_available check to silence this warning}}
+ unsigned B1 = fn5_1(); // #fn5_1_call
+
+ unsigned C1 = fn5_0();
+
+ // expected-error@#fn6_0_s_call {{'fn6_0_s' is unavailable: introduced in Shader Model 6.0 compute shader}}
+ // expected-note@#fn6_0_s {{'fn6_0_s' has been explicitly marked unavailable here}}
+ unsigned A2 = fn6_0_s(); // #fn6_0_s_call
+
+ // expected-error@#fn5_1_s_call {{'fn5_1_s' is unavailable: introduced in Shader Model 5.1 compute shader}}
+ // expected-note@#fn5_1_s {{'fn5_1_s' has been explicitly marked unavailable here}}
+ unsigned B2 = fn5_1_s(); // #fn5_1_s_call
+
+ unsigned C2 = fn5_0_s();
+
+ // expected-warning@#fn6_0_mix_call {{'fn6_0_mix' is only available on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0_mix {{'fn6_0_mix' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
+ // expected-note@#fn6_0_mix_call {{enclose 'fn6_0_mix' in a __builtin_available check to silence this warning}}
+ unsigned A3 = fn6_0_mix(); // #fn6_0_mix_call
+
+ unsigned B3 = fn5_0_mix();
+
+ // expected-error@#fn6_0_mix_s_call {{'fn6_0_mix_s' is unavailable: introduced in Shader Model 6.0 compute shader}}
+ // expected-note@#fn6_0_mix_s {{'fn6_0_mix_s' has been explicitly marked unavailable here}}
+ unsigned A4 = fn6_0_mix_s(); // #fn6_0_mix_s_call
+
+ unsigned B4 = fn5_0_mix_s();
+
+ // expected-warning@#fn6_0_stages1_call {{'fn6_0_stages1' is only available in compute shader environment on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0_stages1 {{'fn6_0_stages1' 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@#fn6_0_stages1_call {{enclose 'fn6_0_stages1' in a __builtin_available check to silence this warning}}
+ unsigned A5 = fn6_0_stages1(); // #fn6_0_stages1_call
+
+ // expected-warning@#fn6_0_stages2_call {{'fn6_0_stages2' is unavailable}}
+ // expected-note@#fn6_0_stages2 {{'fn6_0_stages2' 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@#fn6_0_stages2_call {{enclose 'fn6_0_stages2' in a __builtin_available check to silence this warning}}
+ unsigned B5 = fn6_0_stages2(); // #fn6_0_stages2_call
+
+ unsigned C5 = fn5_0_stages();
+
+ // expected-warning@#fn6_0_stages1_s_call {{'fn6_0_stages1_s' is only available in compute shader environment on Shader Model 6.0 or newer}}
+ // expected-note@#fn6_0_stages1_s {{'fn6_0_stages1_s' 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@#fn6_0_stages1_s_call {{enclose 'fn6_0_stages1_s' in a __builtin_available check to silence this warning}}
+ unsigned A6 = fn6_0_stages1_s(); // #fn6_0_stages1_s_call
+
+ // expected-warning@#fn6_0_stages2_s_call {{'fn6_0_stages2_s' is unavailable}}
+ // expected-note@#fn6_0_stages2_s {{'fn6_0_stages2_s' 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@#fn6_0_stages2_s_call {{enclose 'fn6_0_stages2_s' in a __builtin_available check to silence this warning}}
+ unsigned B6 = fn6_0_stages2_s(); // #fn6_0_stages2_s_call
+
+ unsigned C6 = fn5_0_stages_s();
+
+ return 0;
+}
diff --git a/clang/test/SemaHLSL/AvailabilityMarkup.hlsl b/clang/test/SemaHLSL/AvailabilityMarkup.hlsl
deleted file mode 100644
index ece5ca9d3ea9f..0000000000000
--- a/clang/test/SemaHLSL/AvailabilityMarkup.hlsl
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-library -verify %s
-
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned fn6_0(); // #fn6_0
-
-__attribute__((availability(shadermodel, introduced = 5.1)))
-unsigned fn5_1(); // #fn5_1
-
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned fn5_0();
-
-void fn() {
- // expected-warning@#fn6_0_site {{'fn6_0' is only available on Shader Model 6.0 or newer}}
- // expected-note@#fn6_0 {{'fn6_0' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#fn6_0_site {{enclose 'fn6_0' in a __builtin_available check to silence this warning}}
- unsigned A = fn6_0(); // #fn6_0_site
-
- // expected-warning@#fn5_1_site {{'fn5_1' is only available on Shader Model 5.1 or newer}}
- // expected-note@#fn5_1 {{'fn5_1' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#fn5_1_site {{enclose 'fn5_1' in a __builtin_available check to silence this warning}}
- unsigned B = fn5_1(); // #fn5_1_site
-
- unsigned C = fn5_0();
-}
-
diff --git a/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl b/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
deleted file mode 100644
index 3572cd85dd4ef..0000000000000
--- a/clang/test/SemaHLSL/AvailabilityMarkupStages.hlsl
+++ /dev/null
@@ -1,45 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-unknown-shadermodel5.0-compute -verify %s
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0)))
-unsigned fn6_0_all(); // #fn6_0_all_def
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0)))
-unsigned fn5_0_all();
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh)))
-unsigned fn6_0_stages1(); // #fn6_0_stages1_def
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned fn6_0_stages2(); // #fn6_0_stages2_def
-
-__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel)))
-__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
-__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
-unsigned fn5_0_stages();
-
-void fn() {
-
- // expected-warning@#fn6_0_all_call {{'fn6_0_all' is only available on Shader Model 6.0 or newer}}
- // expected-note@#fn6_0_all_def {{'fn6_0_all' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
- // expected-note@#fn6_0_all_call {{enclose 'fn6_0_all' in a __builtin_available check to silence this warning}}
- unsigned A = fn6_0_all(); // #fn6_0_all_call
-
- unsigned B = fn5_0_all();
-
- // expected-warning@#fn6_0_stages1_call {{'fn6_0_stages1' is only available in compute shader environment on Shader Model 6.0 or newer}}
- // expected-note@#fn6_0_stages1_def {{'fn6_0_stages1' 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@#fn6_0_stages1_call {{enclose 'fn6_0_stages1' in a __builtin_available check to silence this warning}}
- unsigned C = fn6_0_stages1(); // #fn6_0_stages1_call
-
- // expected-warning@#fn6_0_stages2_call {{'fn6_0_stages2' is unavailable}}
- // expected-note@#fn6_0_stages2_def {{'fn6_0_stages2' 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@#fn6_0_stages2_call {{enclose 'fn6_0_stages2' in a __builtin_available check to silence this warning}}
- unsigned E = fn6_0_stages2(); // #fn6_0_stages2_call
-
- unsigned D = fn5_0_stages();
-}
>From 66ad8f1470c769cae4507e8021bfb42f058fd787 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 9 May 2024 16:52:14 -0700
Subject: [PATCH 7/8] Fix test - add numthreads attribute
---
clang/test/Sema/attr-availability-shadermodel.hlsl | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/test/Sema/attr-availability-shadermodel.hlsl b/clang/test/Sema/attr-availability-shadermodel.hlsl
index ef896e99a3c66..3339656354f29 100644
--- a/clang/test/Sema/attr-availability-shadermodel.hlsl
+++ b/clang/test/Sema/attr-availability-shadermodel.hlsl
@@ -75,6 +75,7 @@ __attribute__((availability(shadermodel, introduced = 5.0, environment = compute
__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
unsigned fn5_0_stages_s();
+[numthreads(4,1,1)]
int main() {
// expected-warning@#fn6_0_call {{'fn6_0' is only available on Shader Model 6.0 or newer}}
// expected-note@#fn6_0 {{'fn6_0' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
>From 1e2b724bb250ea70d07d20cc5173133fd1a3b89f Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 14 May 2024 09:11:46 -0700
Subject: [PATCH 8/8] Code review feedback
---
clang/lib/Sema/SemaAvailability.cpp | 46 +++++++++++++----------------
1 file changed, 21 insertions(+), 25 deletions(-)
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index a607a7ba2c2f5..663b6f35b869d 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -421,19 +421,16 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
Introduced);
- if (EnvironmentMatchesOrNone) {
- unsigned DiagKind = UseNewWarning ? diag::warn_unguarded_availability_new
- : diag::warn_unguarded_availability;
-
- S.Diag(Loc, DiagKind)
- << OffendingDecl << PlatformName << Introduced.getAsString()
- << UseEnvironment << TargetEnvironment;
- } else {
- unsigned DiagKind =
- UseNewWarning ? diag::warn_unguarded_availability_unavailable_new
- : diag::warn_unguarded_availability_unavailable;
- S.Diag(Loc, DiagKind) << Loc << OffendingDecl;
- }
+ 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);
+
+ S.Diag(Loc, DiagKind) << OffendingDecl << PlatformName
+ << Introduced.getAsString() << UseEnvironment
+ << TargetEnvironment;
S.Diag(OffendingDecl->getLocation(),
diag::note_partial_availability_specified_here)
@@ -850,18 +847,17 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
bool UseEnvironment =
(!AttrEnvironment.empty() && !TargetEnvironment.empty());
- if (EnvironmentMatchesOrNone) {
- unsigned DiagKind = UseNewDiagKind ? diag::warn_unguarded_availability_new
- : diag::warn_unguarded_availability;
- SemaRef.Diag(Range.getBegin(), DiagKind)
- << Range << D << PlatformName << Introduced.getAsString()
- << UseEnvironment << TargetEnvironment;
- } else {
- unsigned DiagKind =
- UseNewDiagKind ? diag::warn_unguarded_availability_unavailable_new
- : diag::warn_unguarded_availability_unavailable;
- SemaRef.Diag(Range.getBegin(), DiagKind) << Range << D;
- }
+ 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);
+
+ SemaRef.Diag(Range.getBegin(), DiagKind)
+ << Range << D << PlatformName << Introduced.getAsString()
+ << UseEnvironment << TargetEnvironment;
SemaRef.Diag(OffendingDecl->getLocation(),
diag::note_partial_availability_specified_here)
More information about the cfe-commits
mailing list