Skip to content

[Clang][HLSL] Add environment parameter to availability attribute #89809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
May 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
22b67d3
Add environment parameter to clang availability attribute
hekota Apr 23, 2024
3460714
Merge branch 'main' of https://github.com/llvm/llvm-project into avai…
hekota Apr 23, 2024
36eb954
apply clang-format
hekota Apr 23, 2024
0a66eb2
Add tests and documentation, adjust diag messages
hekota Apr 25, 2024
c4b06e9
Merge branch 'main' of https://github.com/llvm/llvm-project into avai…
hekota Apr 26, 2024
c2e4c94
Merge branch 'main' of https://github.com/llvm/llvm-project into avai…
hekota Apr 29, 2024
eac0b91
Remove trailing whitespace
hekota Apr 30, 2024
6505290
Modify diagnostic message when function is not available for target e…
hekota May 7, 2024
2573997
Merge branch 'main' of https://github.com/llvm/llvm-project into avai…
hekota May 8, 2024
22d2d24
Move tests into Sema, add coverage for strict flag
hekota May 8, 2024
66ad8f1
Fix test - add numthreads attribute
hekota May 9, 2024
5984b33
Merge branch 'main' of https://github.com/llvm/llvm-project into avai…
hekota May 10, 2024
958b78e
Merge branch 'main' of https://github.com/llvm/llvm-project into avai…
hekota May 14, 2024
1e2b724
Code review feedback
hekota May 14, 2024
0a3d1f8
Add more tests, disable availability strict parameter use with enviro…
hekota May 15, 2024
48d3168
clang-format
hekota May 15, 2024
ef72635
Address feedback - restricting environment parameter to HLSL only and…
hekota May 15, 2024
7441535
Code review feedback - unify diag message and make it an error
hekota May 16, 2024
055a5d7
One more test update
hekota May 16, 2024
1eeb418
Move tests under SemaHLSL
hekota May 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,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)
Expand All @@ -1019,7 +1019,7 @@ def Availability : InheritableAttr {
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOS (App Extension)")
.Case("swift", "Swift")
.Case("shadermodel", "HLSL ShaderModel")
.Case("shadermodel", "Shader Model")
.Case("ohos", "OpenHarmony OS")
.Default(llvm::StringRef());
}
Expand Down Expand Up @@ -1059,7 +1059,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]>;
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,11 @@ replacement=\ *string-literal*
a warning about use of a deprecated declaration. The Fix-It will replace
the deprecated declaration with the new declaration specified.

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. The parameter is currently supported only in HLSL.

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;
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,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., 'compute'">;

// objc_bridge_related attribute
def err_objcbridge_related_expected_related_class : Error<
Expand Down
17 changes: 14 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3829,6 +3829,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; "
Expand Down Expand Up @@ -3859,13 +3862,21 @@ def note_protocol_method : Note<
def warn_availability_fuchsia_unavailable_minor : Warning<
"Fuchsia API Level prohibits specifying a minor or sub-minor version">,
InGroup<Availability>;
def err_availability_unexpected_parameter: Error<
"unexpected parameter '%0' in availability attribute, not permitted in %select{HLSL|C/C++}1">;

def warn_unguarded_availability :
Warning<"%0 is only available on %1 %2 or newer">,
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<
Expand Down Expand Up @@ -5862,8 +5873,8 @@ 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, "
"but the deployment target is %1 %3">;
"%0 has been marked as being introduced in %1 %2 %select{|in %5 environment }4here, "
"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<
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,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;
Expand Down
42 changes: 28 additions & 14 deletions clang/include/clang/Sema/ParsedAttr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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) {
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;
Expand Down Expand Up @@ -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),
Expand All @@ -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.
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -994,10 +1006,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;
}
Expand Down
15 changes: 8 additions & 7 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -3572,13 +3573,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);
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);
Expand Down
28 changes: 22 additions & 6 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,12 +666,28 @@ 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;
Expand Down
15 changes: 11 additions & 4 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,21 @@ 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

//===----------------------------------------------------------------------===//
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Index/CommentToXML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1052,6 +1053,11 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
}
if (AA->getUnavailable())
Result << "<Unavailable/>";

IdentifierInfo *Environment = AA->getEnvironment();
if (Environment) {
Result << "<Environment>" << Environment->getName() << "</Environment>";
}
Result << "</Availability>";
}
}
Expand Down
20 changes: 19 additions & 1 deletion clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,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);
Expand Down Expand Up @@ -1300,6 +1301,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
Expand Down Expand Up @@ -1347,6 +1349,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);
Expand All @@ -1368,6 +1377,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.
Expand Down Expand Up @@ -1449,7 +1467,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.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaAPINotes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,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 {
Expand Down
Loading
Loading