aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorAlex Coplan <alex.coplan@arm.com>2023-03-17 16:30:51 +0000
committerAlex Coplan <alex.coplan@arm.com>2023-11-27 10:42:55 +0000
commit06280a906cb3dc80cf5e07cf3335b758848d488d (patch)
tree292a91ef3a9c33fd3761b3cff321303b5d03d656 /libcpp
parentd9abaa8d58f5729925b1db735d4723a9ea825eaa (diff)
downloadgcc-06280a906cb3dc80cf5e07cf3335b758848d488d.zip
gcc-06280a906cb3dc80cf5e07cf3335b758848d488d.tar.gz
gcc-06280a906cb3dc80cf5e07cf3335b758848d488d.tar.bz2
c-family: Implement __has_feature and __has_extension [PR60512]
This patch implements clang's __has_feature and __has_extension in GCC. Currently the patch aims to implement all documented features (and some undocumented ones) following the documentation at https://clang.llvm.org/docs/LanguageExtensions.html with the exception of the legacy features for C++ type traits. These are omitted, since as the clang documentation notes, __has_builtin is the correct "modern" way to query for these (which GCC already implements). gcc/c-family/ChangeLog: PR c++/60512 * c-common.cc (struct hf_feature_info): New. (c_common_register_feature): New. (init_has_feature): New. (has_feature_p): New. * c-common.h (c_common_has_feature): New. (c_family_register_lang_features): New. (c_common_register_feature): New. (has_feature_p): New. * c-lex.cc (init_c_lex): Plumb through has_feature callback. (c_common_has_builtin): Generalize and move common part ... (c_common_lex_availability_macro): ... here. (c_common_has_feature): New. * c-ppoutput.cc (init_pp_output): Plumb through has_feature. gcc/c/ChangeLog: PR c++/60512 * c-lang.cc (c_family_register_lang_features): New. * c-objc-common.cc (struct c_feature_info): New. (c_register_features): New. * c-objc-common.h (c_register_features): New. gcc/cp/ChangeLog: PR c++/60512 * cp-lang.cc (c_family_register_lang_features): New. * cp-objcp-common.cc (struct cp_feature_selector): New. (cp_feature_selector::has_feature): New. (struct cp_feature_info): New. (cp_register_features): New. * cp-objcp-common.h (cp_register_features): New. gcc/ChangeLog: PR c++/60512 * doc/cpp.texi: Document __has_{feature,extension}. gcc/objc/ChangeLog: PR c++/60512 * objc-act.cc (struct objc_feature_info): New. (objc_nonfragile_abi_p): New. (objc_common_register_features): New. * objc-act.h (objc_common_register_features): New. * objc-lang.cc (c_family_register_lang_features): New. gcc/objcp/ChangeLog: PR c++/60512 * objcp-lang.cc (c_family_register_lang_features): New. libcpp/ChangeLog: PR c++/60512 * include/cpplib.h (struct cpp_callbacks): Add has_feature. (enum cpp_builtin_type): Add BT_HAS_{FEATURE,EXTENSION}. * init.cc: Add __has_{feature,extension}. * macro.cc (_cpp_builtin_macro_text): Handle BT_HAS_{FEATURE,EXTENSION}. gcc/testsuite/ChangeLog: PR c++/60512 * c-c++-common/has-feature-common.c: New test. * c-c++-common/has-feature-pedantic.c: New test. * g++.dg/ext/has-feature.C: New test. * gcc.dg/asan/has-feature-asan.c: New test. * gcc.dg/has-feature.c: New test. * gcc.dg/ubsan/has-feature-ubsan.c: New test. * obj-c++.dg/has-feature.mm: New test. * objc.dg/has-feature.m: New test. Co-Authored-By: Iain Sandoe <iain@sandoe.co.uk>
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/include/cpplib.h7
-rw-r--r--libcpp/init.cc2
-rw-r--r--libcpp/macro.cc6
3 files changed, 14 insertions, 1 deletions
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index f857ffa..2b66262 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -764,6 +764,9 @@ struct cpp_callbacks
/* Callback to determine whether a built-in function is recognized. */
int (*has_builtin) (cpp_reader *);
+ /* Callback to determine whether a feature is available. */
+ int (*has_feature) (cpp_reader *, bool);
+
/* Callback that can change a user lazy into normal macro. */
void (*user_lazy_macro) (cpp_reader *, cpp_macro *, unsigned);
@@ -968,7 +971,9 @@ enum cpp_builtin_type
BT_HAS_STD_ATTRIBUTE, /* `__has_c_attribute(x)' */
BT_HAS_BUILTIN, /* `__has_builtin(x)' */
BT_HAS_INCLUDE, /* `__has_include(x)' */
- BT_HAS_INCLUDE_NEXT /* `__has_include_next(x)' */
+ BT_HAS_INCLUDE_NEXT, /* `__has_include_next(x)' */
+ BT_HAS_FEATURE, /* `__has_feature(x)' */
+ BT_HAS_EXTENSION /* `__has_extension(x)' */
};
#define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE))
diff --git a/libcpp/init.cc b/libcpp/init.cc
index 250a02a..5dfce4b 100644
--- a/libcpp/init.cc
+++ b/libcpp/init.cc
@@ -435,6 +435,8 @@ static const struct builtin_macro builtin_array[] =
B("__has_builtin", BT_HAS_BUILTIN, true),
B("__has_include", BT_HAS_INCLUDE, true),
B("__has_include_next",BT_HAS_INCLUDE_NEXT, true),
+ B("__has_feature", BT_HAS_FEATURE, true),
+ B("__has_extension", BT_HAS_EXTENSION, true),
/* Keep builtins not used for -traditional-cpp at the end, and
update init_builtins() if any more are added. */
B("_Pragma", BT_PRAGMA, true),
diff --git a/libcpp/macro.cc b/libcpp/macro.cc
index f437da4..6f24a9d 100644
--- a/libcpp/macro.cc
+++ b/libcpp/macro.cc
@@ -677,6 +677,12 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
number = builtin_has_include (pfile, node,
node->value.builtin == BT_HAS_INCLUDE_NEXT);
break;
+
+ case BT_HAS_FEATURE:
+ case BT_HAS_EXTENSION:
+ number = pfile->cb.has_feature (pfile,
+ node->value.builtin == BT_HAS_FEATURE);
+ break;
}
if (result == NULL)