Skip to content

Commit 9682898

Browse files
authored
Merge pull request #11364 from tshortli/introduce-always-available-domain-20240723
[stable/20240723] Introduce `FeatureAvailKind::AlwaysAvailable`
2 parents dca01f7 + a049b79 commit 9682898

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
@@ -64,7 +64,13 @@ enum class PointerAuthenticationMode : unsigned {
6464
SignAndAuth
6565
};
6666

67-
enum class FeatureAvailKind { None, Available, Unavailable, Dynamic };
67+
enum class FeatureAvailKind {
68+
None,
69+
Available,
70+
Unavailable,
71+
Dynamic,
72+
AlwaysAvailable,
73+
};
6874

6975
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
7076
/// 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
@@ -948,6 +948,9 @@ ASTContext::getFeatureAvailInfo(Decl *D) const {
948948
case 2:
949949
Kind = FeatureAvailKind::Dynamic;
950950
break;
951+
case 3:
952+
Kind = FeatureAvailKind::AlwaysAvailable;
953+
break;
951954
default:
952955
llvm_unreachable("invalid feature kind");
953956
}
@@ -990,10 +993,20 @@ bool ASTContext::hasUnavailableFeature(const Decl *D) const {
990993
for (auto *AA : D->specific_attrs<DomainAvailabilityAttr>()) {
991994
auto FeatureName = AA->getDomain();
992995
auto FeatureInfo = getFeatureAvailInfo(FeatureName);
993-
if (FeatureInfo.Kind == (AA->getUnavailable()
994-
? FeatureAvailKind::Available
995-
: FeatureAvailKind::Unavailable))
996-
return true;
996+
switch (FeatureInfo.Kind) {
997+
case FeatureAvailKind::Available:
998+
case FeatureAvailKind::AlwaysAvailable:
999+
if (AA->getUnavailable())
1000+
return true;
1001+
break;
1002+
case FeatureAvailKind::Unavailable:
1003+
if (!AA->getUnavailable())
1004+
return true;
1005+
break;
1006+
case FeatureAvailKind::Dynamic:
1007+
case FeatureAvailKind::None:
1008+
break;
1009+
}
9971010
}
9981011

9991012
return false;

clang/lib/AST/ExprConstant.cpp

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

1199611996
switch (FeatureInfo.Kind) {
1199711997
case FeatureAvailKind::Available:
11998+
case FeatureAvailKind::AlwaysAvailable:
1199811999
ResultInt = 1;
1199912000
break;
1200012001
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
__attribute__((availability(domain:feature1, AVAIL))) void func12(void);
@@ -31,6 +32,8 @@ __attribute__((availability(domain:feature4, AVAIL))) void func10(void);
3132
__attribute__((availability(domain:feature4, UNAVAIL))) void func11(void);
3233
__attribute__((availability(domain:feature4, AVAIL))) int g4;
3334
__attribute__((availability(domain:feature4, UNAVAIL))) int g5;
35+
__attribute__((availability(domain:feature5, AVAIL))) void func21(void);
36+
__attribute__((availability(domain:feature5, UNAVAIL))) void func22(void);
3437
#endif
3538

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

0 commit comments

Comments
 (0)