Skip to content

Commit dcd6381

Browse files
committed
Introduce FeatureAvailKind::AlwaysAvailable.
Represent availability domains that are always available regardless of context by introducing a new `FeatureAvailKind`. The Sema support for these domains will added later; this change is designed to unblock Swift's implementation of support for always available domains. Resolves rdar://160244138.
1 parent aa7f6da commit dcd6381

File tree

5 files changed

+48
-11
lines changed

5 files changed

+48
-11
lines changed

clang/include/clang/Basic/LangOptions.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ enum class PointerAuthenticationMode : unsigned {
6666
SignAndAuth
6767
};
6868

69-
enum class FeatureAvailKind { None, Available, Unavailable, Dynamic };
69+
enum class FeatureAvailKind {
70+
None,
71+
Available,
72+
Unavailable,
73+
Dynamic,
74+
AlwaysAvailable,
75+
};
7076

7177
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
7278
/// this large collection of bitfields is a trivial class type.

clang/lib/AST/ASTContext.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,9 @@ ASTContext::getFeatureAvailInfo(Decl *D) const {
10091009
case 2:
10101010
Kind = FeatureAvailKind::Dynamic;
10111011
break;
1012+
case 3:
1013+
Kind = FeatureAvailKind::AlwaysAvailable;
1014+
break;
10121015
default:
10131016
llvm_unreachable("invalid feature kind");
10141017
}
@@ -1051,10 +1054,20 @@ bool ASTContext::hasUnavailableFeature(const Decl *D) const {
10511054
for (auto *AA : D->specific_attrs<DomainAvailabilityAttr>()) {
10521055
auto FeatureName = AA->getDomain();
10531056
auto FeatureInfo = getFeatureAvailInfo(FeatureName);
1054-
if (FeatureInfo.Kind == (AA->getUnavailable()
1055-
? FeatureAvailKind::Available
1056-
: FeatureAvailKind::Unavailable))
1057-
return true;
1057+
switch (FeatureInfo.Kind) {
1058+
case FeatureAvailKind::Available:
1059+
case FeatureAvailKind::AlwaysAvailable:
1060+
if (AA->getUnavailable())
1061+
return true;
1062+
break;
1063+
case FeatureAvailKind::Unavailable:
1064+
if (!AA->getUnavailable())
1065+
return true;
1066+
break;
1067+
case FeatureAvailKind::Dynamic:
1068+
case FeatureAvailKind::None:
1069+
break;
1070+
}
10581071
}
10591072

10601073
return false;

clang/lib/AST/ExprConstant.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12531,6 +12531,7 @@ class IntExprEvaluator
1253112531

1253212532
switch (FeatureInfo.Kind) {
1253312533
case FeatureAvailKind::Available:
12534+
case FeatureAvailKind::AlwaysAvailable:
1253412535
ResultInt = 1;
1253512536
break;
1253612537
case FeatureAvailKind::Unavailable:

clang/lib/Headers/availability_domain.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define __AVAILABILITY_DOMAIN_ENABLED 0
1616
#define __AVAILABILITY_DOMAIN_DISABLED 1
1717
#define __AVAILABILITY_DOMAIN_DYNAMIC 2
18+
#define __AVAILABILITY_DOMAIN_ALWAYS_ENABLED 3
1819

1920
/// Describes the fields of a Clang availability domain. This struct is an
2021
/// implementation detail of the compiler and is subject to change so don't
@@ -43,11 +44,8 @@ struct __AvailabilityDomain {
4344
availability_domain(domain))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}
4445

4546
#define CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(domain) \
46-
static struct __AvailabilityDomain domain __attribute__(( \
47-
availability_domain(domain))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}
48-
49-
#define CLANG_ALWAYS_DISABLED_AVAILABILITY_DOMAIN(domain) \
50-
static struct __AvailabilityDomain domain __attribute__(( \
51-
availability_domain(domain))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}
47+
static struct __AvailabilityDomain domain \
48+
__attribute__((availability_domain(domain))) = { \
49+
__AVAILABILITY_DOMAIN_ALWAYS_ENABLED, 0}
5250

5351
#endif /* __AVAILABILITY_DOMAIN_H */

clang/test/Sema/feature-availability.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
1313
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
1414
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature3);
1515
CLANG_DYNAMIC_AVAILABILITY_DOMAIN(feature4, pred1);
16+
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature5);
1617
#endif
1718

1819
#pragma clang attribute push (__attribute__((availability(domain:feature1, AVAIL))), apply_to=any(function))
@@ -34,6 +35,8 @@ __attribute__((availability(domain:feature4, AVAIL))) void func10(void);
3435
__attribute__((availability(domain:feature4, UNAVAIL))) void func11(void);
3536
__attribute__((availability(domain:feature4, AVAIL))) int g4;
3637
__attribute__((availability(domain:feature4, UNAVAIL))) int g5;
38+
__attribute__((availability(domain:feature5, AVAIL))) void func21(void);
39+
__attribute__((availability(domain:feature5, UNAVAIL))) void func22(void);
3740
#endif
3841

3942
void test_unreachable_code(void) {
@@ -240,3 +243,19 @@ void test7(void) {
240243
e = EB; // expected-error {{use of 'EB' requires feature 'feature1' to be available}}
241244
}
242245
}
246+
247+
#ifdef USE_DOMAIN
248+
void test8(void) {
249+
// FIXME: Use of 'func21()' should not be diagnosed because feature5 is always available.
250+
func21(); // expected-error {{use of 'func21' requires feature 'feature5' to be available}}
251+
func22(); // expected-error {{use of 'func22' requires feature 'feature5' to be unavailable}}
252+
253+
if (__builtin_available(domain:feature5)) {
254+
func21();
255+
func22(); // expected-error {{use of 'func22' requires feature 'feature5' to be unavailable}}
256+
} else {
257+
func21(); // expected-error {{use of 'func21' requires feature 'feature5' to be available}}
258+
func22();
259+
}
260+
}
261+
#endif

0 commit comments

Comments
 (0)