diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 8ba7fa2479d04..3a24b234263ab 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -927,6 +927,8 @@ ASTContext::getFeatureAvailInfo(Decl *D) const { auto *Attr = VD->getAttr(); if (!Attr) return {}; + if (!VD->getInit()) + return {}; StringRef Name = Attr->getName()->getName(); auto *Init = cast(VD->getInit()); Expr::EvalResult Result; diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 6a19f20695b5d..905d432c8fbe9 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -37,6 +37,7 @@ set(core_files unwind.h varargs.h feature-availability.h + availability_domain.h ) set(arm_common_files diff --git a/clang/lib/Headers/availability_domain.h b/clang/lib/Headers/availability_domain.h new file mode 100644 index 0000000000000..ede75841e2b97 --- /dev/null +++ b/clang/lib/Headers/availability_domain.h @@ -0,0 +1,53 @@ +/*===---- availability_domain.h - Availability Domain -----------------------=== + * + * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://llvm.org/LICENSE.txt for license information. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __AVAILABILITY_DOMAIN_H +#define __AVAILABILITY_DOMAIN_H + +#include + +#define __AVAILABILITY_DOMAIN_ENABLED 0 +#define __AVAILABILITY_DOMAIN_DISABLED 1 +#define __AVAILABILITY_DOMAIN_DYNAMIC 2 + +/// Describes the fields of a Clang availability domain. This struct is an +/// implementation detail of the compiler and is subject to change so don't +/// reference `__AvailabilityDomain` directly. Instead, use the provided macros: +/// +/// CLANG_DYNAMIC_AVAILABILITY_DOMAIN(MyDomain, query); +/// +struct __AvailabilityDomain { + /// The state of the domain (AVAILABLE, UNAVAILABLE, DYNAMIC, etc.). + intptr_t state; + /// An optional function pointer to call to query the availability of a domain + /// at runtime. This should only be non-null for domains in the DYNAMIC state. + int (*const runtimeQuery)(void); +}; + +#define CLANG_DYNAMIC_AVAILABILITY_DOMAIN(domain, query) \ + static struct __AvailabilityDomain domain __attribute__(( \ + availability_domain(domain))) = {__AVAILABILITY_DOMAIN_DYNAMIC, query} + +#define CLANG_ENABLED_AVAILABILITY_DOMAIN(domain) \ + static struct __AvailabilityDomain domain __attribute__(( \ + availability_domain(domain))) = {__AVAILABILITY_DOMAIN_ENABLED, 0} + +#define CLANG_DISABLED_AVAILABILITY_DOMAIN(domain) \ + static struct __AvailabilityDomain domain __attribute__(( \ + availability_domain(domain))) = {__AVAILABILITY_DOMAIN_DISABLED, 0} + +#define CLANG_ALWAYS_ENABLED_AVAILABILITY_DOMAIN(domain) \ + static struct __AvailabilityDomain domain __attribute__(( \ + availability_domain(domain))) = {__AVAILABILITY_DOMAIN_ENABLED, 0} + +#define CLANG_ALWAYS_DISABLED_AVAILABILITY_DOMAIN(domain) \ + static struct __AvailabilityDomain domain __attribute__(( \ + availability_domain(domain))) = {__AVAILABILITY_DOMAIN_DISABLED, 0} + +#endif /* __AVAILABILITY_DOMAIN_H */ diff --git a/clang/lib/Headers/feature-availability.h b/clang/lib/Headers/feature-availability.h index 31abd2e4e081b..6532352f5e855 100644 --- a/clang/lib/Headers/feature-availability.h +++ b/clang/lib/Headers/feature-availability.h @@ -10,24 +10,8 @@ #ifndef __FEATURE_AVAILABILITY_H #define __FEATURE_AVAILABILITY_H -#include +// feature-availability.h is deprecated - use availability_domain.h instead. -/// The possible availability domain states. These values are hardcoded in the -/// compiler and reproduced here for convenience when defining domains. - -#define __AVAILABILITY_DOMAIN_ENABLED 0 -#define __AVAILABILITY_DOMAIN_DISABLED 1 -#define __AVAILABILITY_DOMAIN_DYNAMIC 2 - -/// A struct describing availability domain definitions. This struct definition -/// is just a convenience to ensure that a header defining an availability -/// domain can define it with the arguments that Clang expects at parse time. -struct __AvailabilityDomain { - /// The state of the domain (AVAILABLE, UNAVAILABLE, DYNAMIC, etc.). - intptr_t state; - /// An optional function pointer to call to query the availability of a domain - /// at runtime. This should only be non-null for domains in the DYNAMIC state. - int (*const runtimeQuery)(void); -}; +#include #endif /* __FEATURE_AVAILABILITY_H */ diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap index b196baf1b648f..7fbe87c530472 100644 --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -342,6 +342,11 @@ module feature_availability { export * } +module availability_domain { + header "availability_domain.h" + export * +} + /* TO_UPSTREAM(BoundsSafety) ON */ module ptrcheck { header "ptrcheck.h" diff --git a/clang/test/CodeGen/feature-availability.c b/clang/test/CodeGen/feature-availability.c index adcd6d9d56a1b..4f7d448a6986d 100644 --- a/clang/test/CodeGen/feature-availability.c +++ b/clang/test/CodeGen/feature-availability.c @@ -15,15 +15,15 @@ #ifndef HEADER #define HEADER -#include +#include #define AVAIL 0 #ifdef USE_DOMAIN // DOMAIN: @g3 = extern_weak global i32, align 4 -static struct __AvailabilityDomain feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1); +CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2); #endif __attribute__((availability(domain:feature1, AVAIL))) int func0(void); @@ -94,7 +94,7 @@ void test3(struct S0 *s0) { // DOMAIN-NEXT: ret void int pred1(void); -static struct __AvailabilityDomain feature3 __attribute__((availability_domain(feature3))) = {__AVAILABILITY_DOMAIN_DYNAMIC, pred1}; +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(feature3, pred1); __attribute__((availability(domain:feature3, AVAIL))) int func3(void); __attribute__((availability(domain:feature3, AVAIL))) extern int g3; diff --git a/clang/test/CodeGenObjC/feature-availability.m b/clang/test/CodeGenObjC/feature-availability.m index 14d5c83e42b52..5dd61fe7297bd 100644 --- a/clang/test/CodeGenObjC/feature-availability.m +++ b/clang/test/CodeGenObjC/feature-availability.m @@ -1,16 +1,14 @@ // 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 -#include +#include #define AVAIL 0 #ifdef USE_DOMAIN -int pred1(void); - -static struct __AvailabilityDomain feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; -static struct __AvailabilityDomain feature3 __attribute__((availability_domain(feature3))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1); +CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2); +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature3); #endif // CHECK: @"OBJC_IVAR_$_C0._prop0" = hidden global i32 4, section "__DATA, __objc_ivar", align 4 diff --git a/clang/test/Modules/Inputs/feature-availability/feature1.h b/clang/test/Modules/Inputs/feature-availability/feature1.h index dd3556ffa1c5e..66418a8ba6482 100644 --- a/clang/test/Modules/Inputs/feature-availability/feature1.h +++ b/clang/test/Modules/Inputs/feature-availability/feature1.h @@ -1,7 +1,7 @@ #ifndef FEATURE1_H #define FEATURE1_H -#include +#include -static struct __AvailabilityDomain feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1); #endif diff --git a/clang/test/Modules/Inputs/feature-availability/feature2.h b/clang/test/Modules/Inputs/feature-availability/feature2.h index 734b2dd772f78..9d603e03b9954 100644 --- a/clang/test/Modules/Inputs/feature-availability/feature2.h +++ b/clang/test/Modules/Inputs/feature-availability/feature2.h @@ -1,8 +1,8 @@ #ifndef FEATURE2_H #define FEATURE2_H -#include +#include #include "feature1.h" -static struct __AvailabilityDomain feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2); #endif diff --git a/clang/test/Modules/feature-availability.c b/clang/test/Modules/feature-availability.c index 8433a6ab6018a..e21522facc9d7 100644 --- a/clang/test/Modules/feature-availability.c +++ b/clang/test/Modules/feature-availability.c @@ -3,14 +3,14 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx -fmodules -fmodule-file=%t/feature2.pcm -I %S/Inputs/feature-availability -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple arm64-apple-macosx -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/feature-availability -Werror=non-modular-include-in-module -emit-llvm -o - %s | FileCheck %s -#include +#include #include "feature2.h" #define AVAIL 0 #define UNAVAIL 1 int pred1(void); -static struct __AvailabilityDomain feature3 __attribute__((availability_domain(feature3))) = {__AVAILABILITY_DOMAIN_DYNAMIC, pred1}; +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(feature3, pred1); void func0(void); __attribute__((availability(domain:feature1, AVAIL))) void func1(void); diff --git a/clang/test/Sema/feature-availability.c b/clang/test/Sema/feature-availability.c index dd5bfcac96edd..7ce82e8b0cd5e 100644 --- a/clang/test/Sema/feature-availability.c +++ b/clang/test/Sema/feature-availability.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx15 -fblocks -ffeature-availability=feature1:1 -ffeature-availability=feature2:0 -ffeature-availability=feature3:on -fsyntax-only -Wunreachable-code -verify %s // RUN: %clang_cc1 -triple arm64-apple-macosx15 -fblocks -fsyntax-only -Wunreachable-code -verify -DUSE_DOMAIN %s -#include +#include #define AVAIL 0 #define UNAVAIL 1 @@ -9,10 +9,10 @@ #ifdef USE_DOMAIN int pred1(void); -static struct __AvailabilityDomain __feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain __feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; -static struct __AvailabilityDomain __feature3 __attribute__((availability_domain(feature3))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain __feature4 __attribute__((availability_domain(feature4))) = {__AVAILABILITY_DOMAIN_DYNAMIC, pred1}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1); +CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2); +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature3); +CLANG_DYNAMIC_AVAILABILITY_DOMAIN(feature4, pred1); #endif __attribute__((availability(domain:feature1, AVAIL))) void func12(void); diff --git a/clang/test/SemaObjC/feature-availability.m b/clang/test/SemaObjC/feature-availability.m index e062c668616b9..6916546eae72c 100644 --- a/clang/test/SemaObjC/feature-availability.m +++ b/clang/test/SemaObjC/feature-availability.m @@ -1,15 +1,14 @@ // 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 -#include +#include #define AVAIL 0 #define UNAVAIL 1 #ifdef USE_DOMAIN -int pred1(void); -static struct __AvailabilityDomain feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; +CLANG_ENABLED_AVAILABILITY_DOMAIN(feature1); +CLANG_DISABLED_AVAILABILITY_DOMAIN(feature2); #endif __attribute__((availability(domain:feature1, AVAIL))) int func1(void);