Skip to content

Commit 01c225e

Browse files
authored
[domain availability] Implement Sema support for permanently enabled Unified Feature Flags (#11604)
This implements Sema support for the flag added in 1afc96b. rdar://157602517
1 parent eff752e commit 01c225e

File tree

5 files changed

+49
-18
lines changed

5 files changed

+49
-18
lines changed

clang/lib/Sema/SemaFeatureAvailability.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,18 @@ static bool isFeatureUseGuarded(const DomainAvailabilityAttr *AA,
3333
static void diagnoseDeclFeatureAvailability(const NamedDecl *D,
3434
SourceLocation Loc,
3535
Decl *ContextDecl, Sema &S) {
36-
for (auto *Attr : D->specific_attrs<DomainAvailabilityAttr>())
36+
for (auto *Attr : D->specific_attrs<DomainAvailabilityAttr>()) {
37+
std::string FeatureUse = Attr->getDomain().str();
38+
// Skip checking if the feature is always enabled.
39+
if (!Attr->getUnavailable() &&
40+
S.Context.getFeatureAvailInfo(FeatureUse).Kind ==
41+
FeatureAvailKind::AlwaysAvailable)
42+
continue;
43+
3744
if (!isFeatureUseGuarded(Attr, ContextDecl, S.Context))
3845
S.Diag(Loc, diag::err_unguarded_feature)
39-
<< D << Attr->getDomain().str() << Attr->getUnavailable();
46+
<< D << FeatureUse << Attr->getUnavailable();
47+
}
4048
}
4149

4250
class DiagnoseUnguardedFeatureAvailability
@@ -165,6 +173,12 @@ void DiagnoseUnguardedFeatureAvailability::diagnoseDeclFeatureAvailability(
165173
const NamedDecl *D, SourceLocation Loc) {
166174
for (auto *Attr : D->specific_attrs<DomainAvailabilityAttr>()) {
167175
std::string FeatureUse = Attr->getDomain().str();
176+
// Skip checking if the feature is always enabled.
177+
if (!Attr->getUnavailable() &&
178+
SemaRef.Context.getFeatureAvailInfo(FeatureUse).Kind ==
179+
FeatureAvailKind::AlwaysAvailable)
180+
continue;
181+
168182
if (!isFeatureUseGuarded(Attr))
169183
SemaRef.Diag(Loc, diag::err_unguarded_feature)
170184
<< D << FeatureUse << Attr->getUnavailable();

clang/test/CodeGen/feature-availability.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -emit-llvm -o - %s | FileCheck %s
22
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck --check-prefixes=CHECK,DOMAIN %s
3+
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck --check-prefixes=CHECK,DOMAIN %s
34

45
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -emit-pch -o %t %s
56
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -include-pch %t -emit-llvm -o - %s | FileCheck %s
67

78
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-pch -o %t -DUSE_DOMAIN %s
89
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -include-pch %t -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck --check-prefixes=CHECK,DOMAIN %s
10+
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-pch -o %t -DUSE_DOMAIN -DALWAYS_ENABLED %s
11+
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -include-pch %t -emit-llvm -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck --check-prefixes=CHECK,DOMAIN %s
912

1013
// CHECK: %[[STRUCT_S0:.*]] = type { i32 }
1114
// CHECK: @g0 = external global i32, align 4
@@ -22,7 +25,11 @@
2225
#ifdef USE_DOMAIN
2326
// DOMAIN: @g3 = extern_weak global i32, align 4
2427

28+
#ifdef ALWAYS_ENABLED
29+
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature1);
30+
#else
2531
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
32+
#endif
2633
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
2734
#endif
2835

clang/test/CodeGenObjC/feature-availability.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -ffeature-availability=feature3:on -emit-llvm -o - %s | FileCheck %s
22
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck %s
3+
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck %s
34

45
#include <availability_domain.h>
56

67
#define AVAIL 0
78

89
#ifdef USE_DOMAIN
10+
#ifdef ALWAYS_ENABLED
11+
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature1);
12+
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature3);
13+
#else
914
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
10-
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
1115
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature3);
1216
#endif
17+
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
18+
#endif
1319

1420
// CHECK: @"OBJC_CLASS_$_C0" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C0", ptr null, ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_CLASS_RO_$_C0" }, section "__DATA, __objc_data", align 8
1521
// CHECK-NEXT: @"OBJC_METACLASS_$_C0" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C0", ptr @"OBJC_CLASS_$_C0", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_METACLASS_RO_$_C0" }, section "__DATA, __objc_data", align 8

clang/test/Sema/feature-availability.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,14 @@ void test7(void) {
258258

259259
#ifdef USE_DOMAIN
260260
void test8(void) {
261-
// FIXME: Use of 'func21()' should not be diagnosed because feature5 is always available.
262-
func21(); // expected-error {{cannot use 'func21' because feature 'feature5' is unavailable in this context}}
261+
func21();
263262
func22(); // expected-error {{cannot use 'func22' because feature 'feature5' is available in this context}}
264263

265264
if (__builtin_available(domain:feature5)) {
266265
func21();
267266
func22(); // expected-error {{cannot use 'func22' because feature 'feature5' is available in this context}}
268267
} else {
269-
func21(); // expected-error {{cannot use 'func21' because feature 'feature5' is unavailable in this context}}
268+
func21();
270269
func22();
271270
}
272271
}

clang/test/SemaObjC/feature-availability.m

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
// RUN: %clang_cc1 -fblocks -ffeature-availability=feature1:ON -ffeature-availability=feature2:OFF -fsyntax-only -verify %s
2-
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -DUSE_DOMAIN %s
1+
// RUN: %clang_cc1 -fblocks -ffeature-availability=feature1:ON -ffeature-availability=feature2:OFF -fsyntax-only -verify=expected,enabled %s
2+
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify=expected,enabled -DUSE_DOMAIN %s
3+
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify=expected -DUSE_DOMAIN -DALWAYS_ENABLED %s
34

45
#include <availability_domain.h>
56

67
#define AVAIL 0
78
#define UNAVAIL 1
89

910
#ifdef USE_DOMAIN
11+
#ifdef ALWAYS_ENABLED
12+
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature1);
13+
#else
1014
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
15+
#endif
1116
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
1217
#endif
1318

@@ -19,18 +24,18 @@
1924

2025
@interface C0 {
2126
struct S0 ivar0; // expected-error {{cannot use 'S0' because feature 'feature1' is available in this context}}
22-
struct S1 ivar1; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
27+
struct S1 ivar1; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
2328
struct S1 ivar2 __attribute__((availability(domain:feature1, AVAIL)));
24-
struct S1 ivar3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
29+
struct S1 ivar3 __attribute__((availability(domain:feature1, UNAVAIL))); // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
2530
}
2631
@property struct S0 prop0; // expected-error {{cannot use 'S0' because feature 'feature1' is available in this context}}
27-
@property struct S1 prop1; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
32+
@property struct S1 prop1; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
2833
@property struct S1 prop2 __attribute__((availability(domain:feature1, AVAIL)));
29-
@property struct S1 prop3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
34+
@property struct S1 prop3 __attribute__((availability(domain:feature1, UNAVAIL))); // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
3035
-(struct S0)m0; // expected-error {{cannot use 'S0' because feature 'feature1' is available in this context}}
31-
-(struct S1)m1; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
36+
-(struct S1)m1; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
3237
-(struct S1)m2 __attribute__((availability(domain:feature1, AVAIL)));
33-
-(struct S1)m3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
38+
-(struct S1)m3 __attribute__((availability(domain:feature1, UNAVAIL))); // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
3439
@end
3540

3641
@class Base0;
@@ -59,7 +64,7 @@ @interface NSObject
5964
@interface Base7<T> : NSObject
6065
@end
6166

62-
@interface Derived3 : Base7<Base0 *> // expected-error {{cannot use 'Base0' because feature 'feature1' is unavailable in this context}}
67+
@interface Derived3 : Base7<Base0 *> // enabled-error {{cannot use 'Base0' because feature 'feature1' is unavailable in this context}}
6368
@end
6469

6570
__attribute__((availability(domain:feature1, AVAIL))) // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} expected-note 2 {{feature attribute __attribute__((availability(domain:feature1, 0)))}}
@@ -116,7 +121,7 @@ @interface Derived1(C1) // expected-error {{cannot merge incompatible feature at
116121
@end
117122

118123
@protocol P0
119-
@property struct S1 *p0; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
124+
@property struct S1 *p0; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
120125
@end
121126

122127
__attribute__((availability(domain:feature1, AVAIL)))
@@ -198,8 +203,8 @@ @implementation Derived9 : Base9
198203
-(void)m4 {
199204
// Check that this method doesn't inherit the domain availablity attribute
200205
// from the base class method.
201-
func1(); // expected-error {{cannot use 'func1' because feature 'feature1' is unavailable in this context}}
206+
func1(); // enabled-error {{cannot use 'func1' because feature 'feature1' is unavailable in this context}}
202207

203-
[super m4]; // expected-error {{cannot use 'm4' because feature 'feature1' is unavailable in this context}}
208+
[super m4]; // enabled-error {{cannot use 'm4' because feature 'feature1' is unavailable in this context}}
204209
}
205210
@end

0 commit comments

Comments
 (0)