Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 16 additions & 2 deletions clang/lib/Sema/SemaFeatureAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,18 @@ static bool isFeatureUseGuarded(const DomainAvailabilityAttr *AA,
static void diagnoseDeclFeatureAvailability(const NamedDecl *D,
SourceLocation Loc,
Decl *ContextDecl, Sema &S) {
for (auto *Attr : D->specific_attrs<DomainAvailabilityAttr>())
for (auto *Attr : D->specific_attrs<DomainAvailabilityAttr>()) {
std::string FeatureUse = Attr->getDomain().str();
// Skip checking if the feature is always enabled.
if (!Attr->getUnavailable() &&
S.Context.getFeatureAvailInfo(FeatureUse).Kind ==
FeatureAvailKind::AlwaysAvailable)
continue;

if (!isFeatureUseGuarded(Attr, ContextDecl, S.Context))
S.Diag(Loc, diag::err_unguarded_feature)
<< D << Attr->getDomain().str() << Attr->getUnavailable();
<< D << FeatureUse << Attr->getUnavailable();
}
}

class DiagnoseUnguardedFeatureAvailability
Expand Down Expand Up @@ -165,6 +173,12 @@ void DiagnoseUnguardedFeatureAvailability::diagnoseDeclFeatureAvailability(
const NamedDecl *D, SourceLocation Loc) {
for (auto *Attr : D->specific_attrs<DomainAvailabilityAttr>()) {
std::string FeatureUse = Attr->getDomain().str();
// Skip checking if the feature is always enabled.
if (!Attr->getUnavailable() &&
SemaRef.Context.getFeatureAvailInfo(FeatureUse).Kind ==
FeatureAvailKind::AlwaysAvailable)
continue;

if (!isFeatureUseGuarded(Attr))
SemaRef.Diag(Loc, diag::err_unguarded_feature)
<< D << FeatureUse << Attr->getUnavailable();
Expand Down
7 changes: 7 additions & 0 deletions clang/test/CodeGen/feature-availability.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck --check-prefixes=CHECK,DOMAIN %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck --check-prefixes=CHECK,DOMAIN %s

// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -emit-pch -o %t %s
// 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

// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-pch -o %t -DUSE_DOMAIN %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -include-pch %t -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck --check-prefixes=CHECK,DOMAIN %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-pch -o %t -DUSE_DOMAIN -DALWAYS_ENABLED %s
// 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

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

#ifdef ALWAYS_ENABLED
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature1);
#else
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
#endif
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
#endif

Expand Down
8 changes: 7 additions & 1 deletion clang/test/CodeGenObjC/feature-availability.m
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
// 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
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck %s

#include <availability_domain.h>

#define AVAIL 0

#ifdef USE_DOMAIN
#ifdef ALWAYS_ENABLED
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature1);
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature3);
#else
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature3);
#endif
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
#endif

// 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
// 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
Expand Down
5 changes: 2 additions & 3 deletions clang/test/Sema/feature-availability.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,15 +257,14 @@ void test7(void) {

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

if (__builtin_available(domain:feature5)) {
func21();
func22(); // expected-error {{cannot use 'func22' because feature 'feature5' is available in this context}}
} else {
func21(); // expected-error {{cannot use 'func21' because feature 'feature5' is unavailable in this context}}
func21();
func22();
}
}
Expand Down
29 changes: 17 additions & 12 deletions clang/test/SemaObjC/feature-availability.m
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// RUN: %clang_cc1 -fblocks -ffeature-availability=feature1:ON -ffeature-availability=feature2:OFF -fsyntax-only -verify %s
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -DUSE_DOMAIN %s
// RUN: %clang_cc1 -fblocks -ffeature-availability=feature1:ON -ffeature-availability=feature2:OFF -fsyntax-only -verify=expected,enabled %s
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify=expected,enabled -DUSE_DOMAIN %s
// RUN: %clang_cc1 -fblocks -fsyntax-only -verify=expected -DUSE_DOMAIN -DALWAYS_ENABLED %s

#include <availability_domain.h>

#define AVAIL 0
#define UNAVAIL 1

#ifdef USE_DOMAIN
#ifdef ALWAYS_ENABLED
CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(feature1);
#else
CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1);
#endif
CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2);
#endif

Expand All @@ -19,18 +24,18 @@

@interface C0 {
struct S0 ivar0; // expected-error {{cannot use 'S0' because feature 'feature1' is available in this context}}
struct S1 ivar1; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
struct S1 ivar1; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
struct S1 ivar2 __attribute__((availability(domain:feature1, AVAIL)));
struct S1 ivar3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
struct S1 ivar3 __attribute__((availability(domain:feature1, UNAVAIL))); // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
}
@property struct S0 prop0; // expected-error {{cannot use 'S0' because feature 'feature1' is available in this context}}
@property struct S1 prop1; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
@property struct S1 prop1; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
@property struct S1 prop2 __attribute__((availability(domain:feature1, AVAIL)));
@property struct S1 prop3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
@property struct S1 prop3 __attribute__((availability(domain:feature1, UNAVAIL))); // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
-(struct S0)m0; // expected-error {{cannot use 'S0' because feature 'feature1' is available in this context}}
-(struct S1)m1; // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
-(struct S1)m1; // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
-(struct S1)m2 __attribute__((availability(domain:feature1, AVAIL)));
-(struct S1)m3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
-(struct S1)m3 __attribute__((availability(domain:feature1, UNAVAIL))); // enabled-error {{cannot use 'S1' because feature 'feature1' is unavailable in this context}}
@end

@class Base0;
Expand Down Expand Up @@ -59,7 +64,7 @@ @interface NSObject
@interface Base7<T> : NSObject
@end

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

__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)))}}
Expand Down Expand Up @@ -116,7 +121,7 @@ @interface Derived1(C1) // expected-error {{cannot merge incompatible feature at
@end

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

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

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