mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 15:41:09 +08:00
PR c/66970 - Add __has_builtin() macro
gcc/ChangeLog: PR c/66970 * doc/cpp.texi (__has_builtin): Document. * doc/extend.texi (__builtin_frob_return_addr): Correct spelling. gcc/c/ChangeLog: PR c/66970 * c-decl.c (names_builtin_p): Define a new function. gcc/c-family/ChangeLog: PR c/66970 * c-common.c (c_common_nodes_and_builtins): Call c_define_builtins even when only preprocessing. * c-common.h (names_builtin_p): Declare new function. * c-lex.c (init_c_lex): Set has_builtin. (c_common_has_builtin): Define a new function. * c-ppoutput.c (init_pp_output): Set has_builtin. gcc/cp/ChangeLog: PR c/66970 * cp-objcp-common.c (names_builtin_p): Define new function. gcc/testsuite/ChangeLog: PR c/66970 * c-c++-common/cpp/has-builtin-2.c: New test. * c-c++-common/cpp/has-builtin-3.c: New test. * c-c++-common/cpp/has-builtin.c: New test. From-SVN: r277544
This commit is contained in:
parent
48b2123f63
commit
ad1539d555
@ -1,3 +1,9 @@
|
||||
2019-10-28 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/66970
|
||||
* doc/cpp.texi (__has_builtin): Document.
|
||||
* doc/extend.texi (__builtin_frob_return_addr): Correct spelling.
|
||||
|
||||
2019-10-28 Mihailo Stojanovic <mistojanovic@wavecomp.com>
|
||||
|
||||
PR target/82981
|
||||
|
@ -1,3 +1,13 @@
|
||||
2019-10-28 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/66970
|
||||
* c-common.c (c_common_nodes_and_builtins): Call c_define_builtins
|
||||
even when only preprocessing.
|
||||
* c-common.h (names_builtin_p): Declare new function.
|
||||
* c-lex.c (init_c_lex): Set has_builtin.
|
||||
(c_common_has_builtin): Define a new function.
|
||||
* c-ppoutput.c (init_pp_output): Set has_builtin.
|
||||
|
||||
2019-10-24 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* c-common.h (c_omp_context_selector_matches): Remove.
|
||||
|
@ -4468,8 +4468,7 @@ c_common_nodes_and_builtins (void)
|
||||
va_list_ref_type_node = build_reference_type (va_list_type_node);
|
||||
}
|
||||
|
||||
if (!flag_preprocess_only)
|
||||
c_define_builtins (va_list_ref_type_node, va_list_arg_type_node);
|
||||
c_define_builtins (va_list_ref_type_node, va_list_arg_type_node);
|
||||
|
||||
main_identifier_node = get_identifier ("main");
|
||||
|
||||
|
@ -801,6 +801,7 @@ extern void c_register_addr_space (const char *str, addr_space_t as);
|
||||
extern bool in_late_binary_op;
|
||||
extern const char *c_addr_space_name (addr_space_t as);
|
||||
extern tree identifier_global_value (tree);
|
||||
extern bool names_builtin_p (const char *);
|
||||
extern tree c_linkage_bindings (tree);
|
||||
extern void record_builtin_type (enum rid, const char *, tree);
|
||||
extern tree build_void_list_node (void);
|
||||
@ -1022,6 +1023,7 @@ extern bool c_cpp_diagnostic (cpp_reader *, enum cpp_diagnostic_level,
|
||||
const char *, va_list *)
|
||||
ATTRIBUTE_GCC_DIAG(5,0);
|
||||
extern int c_common_has_attribute (cpp_reader *);
|
||||
extern int c_common_has_builtin (cpp_reader *);
|
||||
|
||||
extern bool parse_optimize_options (tree, bool);
|
||||
|
||||
|
@ -81,6 +81,7 @@ init_c_lex (void)
|
||||
cb->valid_pch = c_common_valid_pch;
|
||||
cb->read_pch = c_common_read_pch;
|
||||
cb->has_attribute = c_common_has_attribute;
|
||||
cb->has_builtin = c_common_has_builtin;
|
||||
cb->get_source_date_epoch = cb_get_source_date_epoch;
|
||||
cb->get_suggestion = cb_get_suggestion;
|
||||
cb->remap_filename = remap_macro_filename;
|
||||
@ -386,6 +387,58 @@ c_common_has_attribute (cpp_reader *pfile)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Callback for has_builtin. */
|
||||
|
||||
int
|
||||
c_common_has_builtin (cpp_reader *pfile)
|
||||
{
|
||||
const cpp_token *token = get_token_no_padding (pfile);
|
||||
if (token->type != CPP_OPEN_PAREN)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"missing '(' after \"__has_builtin\"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *name = "";
|
||||
token = get_token_no_padding (pfile);
|
||||
if (token->type == CPP_NAME)
|
||||
{
|
||||
name = (const char *) cpp_token_as_text (pfile, token);
|
||||
token = get_token_no_padding (pfile);
|
||||
if (token->type != CPP_CLOSE_PAREN)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"expected ')' after \"%s\"", name);
|
||||
name = "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"macro \"__has_builtin\" requires an identifier");
|
||||
if (token->type == CPP_CLOSE_PAREN)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Consume tokens up to the closing parenthesis, including any nested
|
||||
pairs of parentheses, to avoid confusing redundant errors. */
|
||||
for (unsigned nparen = 1; ; token = get_token_no_padding (pfile))
|
||||
{
|
||||
if (token->type == CPP_OPEN_PAREN)
|
||||
++nparen;
|
||||
else if (token->type == CPP_CLOSE_PAREN)
|
||||
--nparen;
|
||||
else if (token->type == CPP_EOF)
|
||||
break;
|
||||
if (!nparen)
|
||||
break;
|
||||
}
|
||||
|
||||
return names_builtin_p (name);
|
||||
}
|
||||
|
||||
|
||||
/* Read a token and return its type. Fill *VALUE with its value, if
|
||||
applicable. Fill *CPP_FLAGS with the token's flags, if it is
|
||||
|
@ -151,6 +151,7 @@ init_pp_output (FILE *out_stream)
|
||||
}
|
||||
|
||||
cb->has_attribute = c_common_has_attribute;
|
||||
cb->has_builtin = c_common_has_builtin;
|
||||
cb->get_source_date_epoch = cb_get_source_date_epoch;
|
||||
cb->remap_filename = remap_macro_filename;
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-10-28 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/66970
|
||||
* c-decl.c (names_builtin_p): Define a new function.
|
||||
|
||||
2019-10-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR c/92249
|
||||
|
@ -9990,6 +9990,34 @@ identifier_global_value (tree t)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Returns true if NAME refers to a built-in function or function-like
|
||||
operator. */
|
||||
|
||||
bool
|
||||
names_builtin_p (const char *name)
|
||||
{
|
||||
tree id = get_identifier (name);
|
||||
if (tree decl = identifier_global_value (id))
|
||||
return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl);
|
||||
|
||||
/* Also detect common reserved C words that aren't strictly built-in
|
||||
functions. */
|
||||
switch (C_RID_CODE (id))
|
||||
{
|
||||
case RID_BUILTIN_CONVERTVECTOR:
|
||||
case RID_BUILTIN_HAS_ATTRIBUTE:
|
||||
case RID_BUILTIN_SHUFFLE:
|
||||
case RID_CHOOSE_EXPR:
|
||||
case RID_OFFSETOF:
|
||||
case RID_TYPES_COMPATIBLE_P:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* In C, the only C-linkage public declaration is at file scope. */
|
||||
|
||||
tree
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-10-28 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/66970
|
||||
* cp-objcp-common.c (names_builtin_p): Define new function.
|
||||
|
||||
2019-10-28 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* parser.h (struct cp_token): Drop {ENUM,BOOL}_BITFIELD C-ism.
|
||||
|
@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "cp-tree.h"
|
||||
#include "cp-objcp-common.h"
|
||||
#include "dwarf2.h"
|
||||
#include "stringpool.h"
|
||||
|
||||
/* Special routine to get the alias set for C++. */
|
||||
|
||||
@ -348,6 +349,77 @@ identifier_global_value (tree name)
|
||||
return get_global_binding (name);
|
||||
}
|
||||
|
||||
/* Returns true if NAME refers to a built-in function or function-like
|
||||
operator. */
|
||||
|
||||
bool
|
||||
names_builtin_p (const char *name)
|
||||
{
|
||||
tree id = get_identifier (name);
|
||||
if (tree binding = get_global_binding (id))
|
||||
{
|
||||
if (TREE_CODE (binding) == FUNCTION_DECL && DECL_IS_BUILTIN (binding))
|
||||
return true;
|
||||
|
||||
/* Handle the case when an overload for a built-in name exists. */
|
||||
if (TREE_CODE (binding) != OVERLOAD)
|
||||
return false;
|
||||
|
||||
for (ovl_iterator it (binding); it; ++it)
|
||||
{
|
||||
tree decl = *it;
|
||||
if (DECL_IS_BUILTIN (decl))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also detect common reserved C++ words that aren't strictly built-in
|
||||
functions. */
|
||||
switch (C_RID_CODE (id))
|
||||
{
|
||||
case RID_ADDRESSOF:
|
||||
case RID_BUILTIN_CONVERTVECTOR:
|
||||
case RID_BUILTIN_HAS_ATTRIBUTE:
|
||||
case RID_BUILTIN_SHUFFLE:
|
||||
case RID_BUILTIN_LAUNDER:
|
||||
case RID_OFFSETOF:
|
||||
case RID_HAS_NOTHROW_ASSIGN:
|
||||
case RID_HAS_NOTHROW_CONSTRUCTOR:
|
||||
case RID_HAS_NOTHROW_COPY:
|
||||
case RID_HAS_TRIVIAL_ASSIGN:
|
||||
case RID_HAS_TRIVIAL_CONSTRUCTOR:
|
||||
case RID_HAS_TRIVIAL_COPY:
|
||||
case RID_HAS_TRIVIAL_DESTRUCTOR:
|
||||
case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS:
|
||||
case RID_HAS_VIRTUAL_DESTRUCTOR:
|
||||
case RID_IS_ABSTRACT:
|
||||
case RID_IS_AGGREGATE:
|
||||
case RID_IS_BASE_OF:
|
||||
case RID_IS_CLASS:
|
||||
case RID_IS_EMPTY:
|
||||
case RID_IS_ENUM:
|
||||
case RID_IS_FINAL:
|
||||
case RID_IS_LITERAL_TYPE:
|
||||
case RID_IS_POD:
|
||||
case RID_IS_POLYMORPHIC:
|
||||
case RID_IS_SAME_AS:
|
||||
case RID_IS_STD_LAYOUT:
|
||||
case RID_IS_TRIVIAL:
|
||||
case RID_IS_TRIVIALLY_ASSIGNABLE:
|
||||
case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
case RID_IS_TRIVIALLY_COPYABLE:
|
||||
case RID_IS_UNION:
|
||||
case RID_IS_ASSIGNABLE:
|
||||
case RID_IS_CONSTRUCTIBLE:
|
||||
case RID_UNDERLYING_TYPE:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Register c++-specific dumps. */
|
||||
|
||||
void
|
||||
|
@ -3159,6 +3159,7 @@ directive}: @samp{#if}, @samp{#ifdef} or @samp{#ifndef}.
|
||||
* Elif::
|
||||
* @code{__has_attribute}::
|
||||
* @code{__has_cpp_attribute}::
|
||||
* @code{__has_builtin}::
|
||||
* @code{__has_include}::
|
||||
@end menu
|
||||
|
||||
@ -3478,6 +3479,33 @@ information including the dates of the introduction of current standard
|
||||
attributes, see @w{@uref{https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations/,
|
||||
SD-6: SG10 Feature Test Recommendations}}.
|
||||
|
||||
@node @code{__has_builtin}
|
||||
@subsection @code{__has_builtin}
|
||||
@cindex @code{__has_builtin}
|
||||
|
||||
The special operator @code{__has_builtin (@var{operand})} may be used in
|
||||
constant integer contexts and in preprocessor @samp{#if} and @samp{#elif}
|
||||
expressions to test whether the symbol named by its @var{operand} is
|
||||
recognized as a built-in function by GCC in the current language and
|
||||
conformance mode. It evaluates to a constant integer with a nonzero
|
||||
value if the argument refers to such a function, and to zero otherwise.
|
||||
The operator may also be used in preprocessor @samp{#if} and @samp{#elif}
|
||||
expressions. The @code{__has_builtin} operator by itself, without any
|
||||
@var{operand} or parentheses, acts as a predefined macro so that support
|
||||
for it can be tested in portable code. Thus, the recommended use of
|
||||
the operator is as follows:
|
||||
|
||||
@smallexample
|
||||
#if defined __has_builtin
|
||||
# if __has_builtin (__builtin_object_size)
|
||||
# define builtin_object_size(ptr) __builtin_object_size (ptr, 2)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef builtin_object_size
|
||||
# define builtin_object_size(ptr) ((size_t)-1)
|
||||
#endif
|
||||
@end smallexample
|
||||
|
||||
@node @code{__has_include}
|
||||
@subsection @code{__has_include}
|
||||
@cindex @code{__has_include}
|
||||
|
@ -10912,7 +10912,7 @@ executed.
|
||||
If no fixup is needed, this function simply passes through @var{addr}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Built-in Function} {void *} __builtin_frob_return_address (void *@var{addr})
|
||||
@deftypefn {Built-in Function} {void *} __builtin_frob_return_addr (void *@var{addr})
|
||||
This function does the reverse of @code{__builtin_extract_return_addr}.
|
||||
@end deftypefn
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
2019-10-28 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/66970
|
||||
* c-c++-common/cpp/has-builtin-2.c: New test.
|
||||
* c-c++-common/cpp/has-builtin-3.c: New test.
|
||||
* c-c++-common/cpp/has-builtin.c: New test.
|
||||
|
||||
2019-10-28 Mihailo Stojanovic <mistojanovic@wavecomp.com>
|
||||
|
||||
PR target/82981
|
||||
|
297
gcc/testsuite/c-c++-common/cpp/has-builtin-2.c
Normal file
297
gcc/testsuite/c-c++-common/cpp/has-builtin-2.c
Normal file
@ -0,0 +1,297 @@
|
||||
/* PR c/66970 - Add __has_builtin() macro
|
||||
Verify __has_builtin evaluation for common built-ins and other identifiers.
|
||||
{ dg-do compile } */
|
||||
|
||||
// Verify a few library built-ins.
|
||||
#if !__has_builtin (__builtin_abs)
|
||||
# error "__has_builtin (__builtin_abs) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (abs)
|
||||
// abs is also a built-in unless disabled by -fno-builtin.
|
||||
# error "__has_builtin (abs) failed"
|
||||
#endif
|
||||
|
||||
#if __cplusplus
|
||||
// Declare an overload and verify that __has_builtin (isalpha) still
|
||||
// evaluates to true.
|
||||
int isalpha (const char*);
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_isalpha)
|
||||
# error "__has_builtin (__builtin_isalpha) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (isalpha)
|
||||
// isalpha is still a built-in despite the overload above.
|
||||
# error "__has_builtin (isalpha) failed"
|
||||
#endif
|
||||
|
||||
|
||||
#if !__has_builtin (__builtin__Exit)
|
||||
# error "__has_builtin (__builtin__Exit) failed"
|
||||
#endif
|
||||
|
||||
|
||||
#if !__has_builtin (__builtin_alloca)
|
||||
# error "__has_builtin (__builtin_alloca) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_is_constant_evaluated)
|
||||
// __builtin_is_constant_evaluated is a C++-only built.
|
||||
# ifdef __cplusplus
|
||||
# error "__has_builtin (__builtin_is_constant_evaluated) failed"
|
||||
# endif
|
||||
#else
|
||||
# ifndef __cplusplus
|
||||
# error "__has_builtin (__builtin_is_constant_evaluated) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_expect)
|
||||
# error "__has_builtin (__builtin_expect) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_trap)
|
||||
# error "__has_builtin (__builtin_trap) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_unreachable)
|
||||
# error "__has_builtin (__builtin_unreachable) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_LINE)
|
||||
# error "__has_builtin (__builtin_LINE) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_object_size)
|
||||
# error "__has_builtin (__builtin_object_size) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_inf)
|
||||
# error "__has_builtin (__builtin_inf) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_nan)
|
||||
# error "__has_builtin (__builtin_nan) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_bswap16)
|
||||
# error "__has_builtin (__builtin_bswap16) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_bswap32)
|
||||
# error "__has_builtin (__builtin_bswap32) failed"
|
||||
#endif
|
||||
|
||||
|
||||
// Verify a few integer overflow built-ins.
|
||||
#if !__has_builtin (__builtin_add_overflow)
|
||||
# error "__has_builtin (__builtin_add_overflow) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_sadd_overflow)
|
||||
# error "__has_builtin (__builtin_sadd_overflow) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_add_overflow_p)
|
||||
# error "__has_builtin (__builtin_add_overflow_p) failed"
|
||||
#endif
|
||||
|
||||
|
||||
// Verify a few atomic built-ins.
|
||||
#if !__has_builtin (__atomic_load)
|
||||
# error "__has_builtin (__atomic_load) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__atomic_load_n)
|
||||
# error "__has_builtin (__atomic_load_n) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__atomic_store)
|
||||
# error "__has_builtin (__atomic_store) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__atomic_store_n)
|
||||
# error "__has_builtin (__atomic_store_n) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__atomic_exchange)
|
||||
# error "__has_builtin (__atomic_echange) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__atomic_exchange_n)
|
||||
# error "__has_builtin (__atomic_exchange_n) failed"
|
||||
#endif
|
||||
|
||||
|
||||
// Verify a few sync built-ins.
|
||||
#if !__has_builtin (__sync_fetch_and_add)
|
||||
# error "__has_builtin (__sync_fetch_and_add) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__sync_add_and_fetch)
|
||||
# error "__has_builtin (__sync_add_and_fetch) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__sync_bool_compare_and_swap)
|
||||
# error "__has_builtin (__sync_bool_compare_and_swap) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__sync_val_compare_and_swap)
|
||||
# error "__has_builtin (__sync_val_compare_and_swap) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__sync_synchronize)
|
||||
# error "__has_builtin (__sync_synchronize) failed"
|
||||
#endif
|
||||
|
||||
// Verify nonlocal goto builtins.
|
||||
#if !__has_builtin (__builtin_setjmp)
|
||||
# error "__has_builtin (__builtin_setjmp) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_longjmp)
|
||||
# error "__has_builtin (__builtin_longjmp) failed"
|
||||
#endif
|
||||
|
||||
|
||||
// Verify a few built-ins for constructing function calls.
|
||||
|
||||
#if !__has_builtin (__builtin_apply)
|
||||
# error "__has_builtin (__builtin_apply) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_return)
|
||||
# error "__has_builtin (__builtin_return) failed"
|
||||
#endif
|
||||
|
||||
// Verify built-ins for function return address.
|
||||
#if !__has_builtin (__builtin_return_address)
|
||||
# error "__has_builtin (__builtin_return_address) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_extract_return_addr)
|
||||
# error "__has_builtin (__builtin_extract_return_addr) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_frob_return_addr)
|
||||
# error "__has_builtin (__builtin_frob_return_addr) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_frame_address)
|
||||
# error "__has_builtin (__builtin_frame_address) failed"
|
||||
#endif
|
||||
|
||||
// Verify keywords that aren't declared built-in functions.
|
||||
|
||||
#if !__has_builtin (__builtin_has_attribute)
|
||||
# error "__has_builtin (__builtin_has_attribute) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_offsetof)
|
||||
# error "__has_builtin (__builtin_offsetof) failed"
|
||||
#endif
|
||||
|
||||
// Verify some C-only built-ins.
|
||||
|
||||
#if !__has_builtin (__builtin_types_compatible_p)
|
||||
# if !__cplusplus
|
||||
# error "__has_builtin (__builtin_types_compatible_p) failed"
|
||||
# endif
|
||||
#else
|
||||
# if __cplusplus
|
||||
# error "__has_builtin (__builtin_types_compatible_p) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Verify a few C++ traits built-ins.
|
||||
|
||||
#if !__has_builtin (__builtin_addressof)
|
||||
# if __cplusplus
|
||||
# error "__has_builtin (__builtin_addressof) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !__cplusplus
|
||||
# error "__has_builtin (__builtin_addressof) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__builtin_launder)
|
||||
# if __cplusplus
|
||||
# error "__has_builtin (__builtin_launder) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !__cplusplus
|
||||
# error "__has_builtin (__builtin_launder) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__has_nothrow_assign)
|
||||
# if __cplusplus
|
||||
# error "__has_builtin (__has_nothrow_assign) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !__cplusplus
|
||||
# error "__has_builtin (__has_nothrow_assign) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__has_trivial_assign)
|
||||
# if __cplusplus
|
||||
# error "__has_builtin (__has_trivial_assign) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !__cplusplus
|
||||
# error "__has_builtin (__has_trivial_assign) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (__has_virtual_destructor)
|
||||
# if __cplusplus
|
||||
# error "__has_builtin (__has_virtual_destructor) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !__cplusplus
|
||||
# error "__has_builtin (__has_virtual_destructor) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// Verify an Intel built-in that's not implemented by any other target.
|
||||
#if !__has_builtin (__builtin_ia32_pause)
|
||||
# if defined (__i386__) || defined (__x86_64__)
|
||||
# error "__has_builtin (__builtin_ia32_pause) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !defined (__i386__) && !defined (__x86_64__)
|
||||
# error "__has_builtin (__builtin_ia32_pause) failed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// Verify non-functions.
|
||||
|
||||
#if __has_builtin (__alignof__)
|
||||
# error "__has_builtin (__alignof__) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (asm)
|
||||
# error "__has_builtin (asm) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (__asm__)
|
||||
# error "__has_builtin (__asm__) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (__attribute__)
|
||||
# error "__has_builtin (__attribute__) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (__inline__)
|
||||
# error "__has_builtin (__inline__) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (__typeof__)
|
||||
# error "__has_builtin (__typeof__) failed"
|
||||
#endif
|
36
gcc/testsuite/c-c++-common/cpp/has-builtin-3.c
Normal file
36
gcc/testsuite/c-c++-common/cpp/has-builtin-3.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* PR c/66970 - Add __has_builtin() macro
|
||||
Verify __has_builtin evaluation for disabled library built-ins.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-fno-builtin-abs" }
|
||||
{ dg-additional-options "-std=c90" { target c } } */
|
||||
|
||||
#if !__has_builtin (__builtin_abs)
|
||||
// __builtin_xxx is always available regardless of -fno-builtin.
|
||||
# error "__has_builtin (__builtin_abs) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (abs)
|
||||
# error "__has_builtin (abs) failed"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (abs)
|
||||
# error "__has_builtin (abs) failed"
|
||||
#endif
|
||||
|
||||
|
||||
#if !__has_builtin (__builtin_vsnprintf)
|
||||
// __builtin_vsnprintf is available in all language modes.
|
||||
# error "__has_builtin (__builtin_vsnprintf) failed"
|
||||
#endif
|
||||
|
||||
#if !__has_builtin (vsnprintf)
|
||||
# if __cplusplus
|
||||
// vsnprintf is always available in C++.
|
||||
# error "__has_builtin (vsnprintf) failed"
|
||||
# endif
|
||||
#else
|
||||
# if !__cplusplus
|
||||
// vsnprintf is a C99 function not available in C90.
|
||||
# error "__has_builtin (vsnprintf) failed"
|
||||
# endif
|
||||
#endif
|
49
gcc/testsuite/c-c++-common/cpp/has-builtin.c
Normal file
49
gcc/testsuite/c-c++-common/cpp/has-builtin.c
Normal file
@ -0,0 +1,49 @@
|
||||
/* PR c/66970 - Add __has_builtin() macro
|
||||
Verify that errors are detected and handled gracefully.
|
||||
{ dg-do compile } */
|
||||
|
||||
#ifndef __has_builtin
|
||||
# error "__has_builtin is not defined"
|
||||
#endif
|
||||
|
||||
#if __has_builtin // { dg-error "missing '\\\(' after \"__has_builtin\"" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin ( // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin () // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin (1) // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin (1, 2) // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin (1 + 2) // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin (x, y) // { dg-error "expected '\\\)' after \"x\"" } */
|
||||
#endif
|
||||
|
||||
#if __has_builtin (x + 1) // { dg-error "expected '\\\)' after \"x\"" } */
|
||||
#endif
|
||||
|
||||
#if __has_builtin (p->i) // { dg-error "expected '\\\)' after \"p\"" } */
|
||||
#endif
|
||||
|
||||
#if __has_builtin ((x)) // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin ((y) // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin ((((z) // { dg-error "macro \"__has_builtin\" requires an identifier" }
|
||||
#endif
|
||||
|
||||
#if __has_builtin (x))) // { dg-error "missing '\\\('" }"
|
||||
#endif
|
||||
|
||||
#if __has_builtin (f ()) // { dg-error "expected '\\\)' after \"f\"" }"
|
||||
#endif
|
@ -676,6 +676,9 @@ struct cpp_callbacks
|
||||
/* Callback to identify whether an attribute exists. */
|
||||
int (*has_attribute) (cpp_reader *);
|
||||
|
||||
/* Callback to determine whether a built-in function is recognized. */
|
||||
int (*has_builtin) (cpp_reader *);
|
||||
|
||||
/* Callback that can change a user lazy into normal macro. */
|
||||
void (*user_lazy_macro) (cpp_reader *, cpp_macro *, unsigned);
|
||||
|
||||
@ -855,7 +858,8 @@ enum cpp_builtin_type
|
||||
BT_PRAGMA, /* `_Pragma' operator */
|
||||
BT_TIMESTAMP, /* `__TIMESTAMP__' */
|
||||
BT_COUNTER, /* `__COUNTER__' */
|
||||
BT_HAS_ATTRIBUTE /* `__has_attribute__(x)' */
|
||||
BT_HAS_ATTRIBUTE, /* `__has_attribute__(x)' */
|
||||
BT_HAS_BUILTIN /* `__has_builtin(x)' */
|
||||
};
|
||||
|
||||
#define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE))
|
||||
|
@ -403,6 +403,7 @@ static const struct builtin_macro builtin_array[] =
|
||||
B("__COUNTER__", BT_COUNTER, true),
|
||||
B("__has_attribute", BT_HAS_ATTRIBUTE, true),
|
||||
B("__has_cpp_attribute", BT_HAS_ATTRIBUTE, true),
|
||||
B("__has_builtin", BT_HAS_BUILTIN, 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),
|
||||
@ -483,7 +484,8 @@ cpp_init_special_builtins (cpp_reader *pfile)
|
||||
|
||||
for (b = builtin_array; b < builtin_array + n; b++)
|
||||
{
|
||||
if (b->value == BT_HAS_ATTRIBUTE
|
||||
if ((b->value == BT_HAS_ATTRIBUTE
|
||||
|| b->value == BT_HAS_BUILTIN)
|
||||
&& (CPP_OPTION (pfile, lang) == CLK_ASM
|
||||
|| pfile->cb.has_attribute == NULL))
|
||||
continue;
|
||||
|
@ -568,6 +568,10 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
|
||||
case BT_HAS_ATTRIBUTE:
|
||||
number = pfile->cb.has_attribute (pfile);
|
||||
break;
|
||||
|
||||
case BT_HAS_BUILTIN:
|
||||
number = pfile->cb.has_builtin (pfile);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
|
@ -326,9 +326,9 @@ static inline bool
|
||||
fun_like_macro (cpp_hashnode *node)
|
||||
{
|
||||
if (cpp_builtin_macro_p (node))
|
||||
return node->value.builtin == BT_HAS_ATTRIBUTE;
|
||||
else
|
||||
return node->value.macro->fun_like;
|
||||
return (node->value.builtin == BT_HAS_ATTRIBUTE
|
||||
|| node->value.builtin == BT_HAS_BUILTIN);
|
||||
return node->value.macro->fun_like;
|
||||
}
|
||||
|
||||
/* Set up state for finding the opening '(' of a function-like
|
||||
|
Loading…
x
Reference in New Issue
Block a user