From 1d00f8c86324c40ab2ba7933366d380e32c0a94a Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 12 Nov 2020 21:13:51 +0000 Subject: c: C2x __has_c_attribute C2x adds the __has_c_attribute preprocessor operator, similar to C++ __has_cpp_attribute. GCC implements __has_cpp_attribute as exactly equivalent to __has_attribute. (The documentation says they differ regarding the values returned for standard attributes, but that's actually only a matter of the particular nonzero value returned not being specified in the documentation for __has_attribute; the implementation makes no distinction between the two.) I don't think having them exactly equivalent is actually correct, either for __has_cpp_attribute or for __has_c_attribute. Specifically, I think it is only correct for __has_cpp_attribute or __has_c_attribute to return nonzero if the given attribute is supported, with the particular pp-tokens passed to __has_cpp_attribute or __has_c_attribute, with [[]] syntax, not if it's only accepted in __attribute__ or with gnu:: added in [[]]. For example, they should return nonzero for gnu::packed, but zero for plain packed, because [[gnu::packed]] is accepted but [[packed]] is ignored as not a standard attribute. This patch implements that for __has_c_attribute, leaving any changes to __has_cpp_attribute for the C++ maintainers. A new BT_HAS_STD_ATTRIBUTE is added for __has_c_attribute (which I think, based on the above, would actually be correct to use for __has_cpp_attribute as well). The code in c_common_has_attribute that deals with scopes has its C++ conditional removed; instead, whether the language is C or C++ is used only to determine the numeric values returned for standard attributes (and which standard attributes are handled there at all). A new argument is passed to c_common_has_attribute to distinguish BT_HAS_STD_ATTRIBUTE from BT_HAS_ATTRIBUTE, and that argument is used to stop attributes with no scope specified from being accepted with __has_c_attribute unless they are one of the known standard attributes and so handled specially. Although the standard specify constants ending with 'L' as the values for the standard attributes, there is no correctness issue with the lack of code in GCC to add that 'L' to the expansion: __has_c_attribute and __has_cpp_attribute are expanded in #if after other macro expansion has occurred, with no semantics being specified if they occur outside #if, so there is no way for a conforming program to inspect the exact text of the expansion of those macros, only to use the resulting pp-number in a #if expression, where long and int have the same set of values. Bootstrapped with no regressions for x86_64-pc-linux-gnu. gcc/ 2020-11-12 Joseph Myers * doc/cpp.texi (__has_attribute): Document when scopes are allowed for C. (__has_c_attribute): New. gcc/c-family/ 2020-11-12 Joseph Myers * c-lex.c (c_common_has_attribute): Take argument std_syntax. Allow scope for C. Handle standard attributes for C. Do not accept unscoped attributes if std_syntax and not handled as standard attributes. * c-common.h (c_common_has_attribute): Update prototype. gcc/testsuite/ 2020-11-12 Joseph Myers * gcc.dg/c2x-has-c-attribute-1.c, gcc.dg/c2x-has-c-attribute-2.c, gcc.dg/c2x-has-c-attribute-3.c, gcc.dg/c2x-has-c-attribute-4.c: New tests. libcpp/ 2020-11-12 Joseph Myers * include/cpplib.h (struct cpp_callbacks): Add bool argument to has_attribute. (enum cpp_builtin_type): Add BT_HAS_STD_ATTRIBUTE. * init.c (builtin_array): Add __has_c_attribute. (cpp_init_special_builtins): Handle BT_HAS_STD_ATTRIBUTE. * macro.c (_cpp_builtin_macro_text): Handle BT_HAS_STD_ATTRIBUTE. Update call to has_attribute for BT_HAS_ATTRIBUTE. * traditional.c (fun_like_macro): Handle BT_HAS_STD_ATTRIBUTE. --- libcpp/include/cpplib.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libcpp/include') diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index c4d7cc5..8900e77 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -672,7 +672,7 @@ struct cpp_callbacks void (*used) (cpp_reader *, location_t, cpp_hashnode *); /* Callback to identify whether an attribute exists. */ - int (*has_attribute) (cpp_reader *); + int (*has_attribute) (cpp_reader *, bool); /* Callback to determine whether a built-in function is recognized. */ int (*has_builtin) (cpp_reader *); @@ -857,6 +857,7 @@ enum cpp_builtin_type BT_TIMESTAMP, /* `__TIMESTAMP__' */ BT_COUNTER, /* `__COUNTER__' */ BT_HAS_ATTRIBUTE, /* `__has_attribute(x)' */ + 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)' */ -- cgit v1.1