diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-09-20 18:37:29 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-09-20 18:37:29 +0200 |
commit | 53d834a7fae3afffebb45a2d66908f705773a7fc (patch) | |
tree | 4af979256b3f85649ada1d5cabc08c21cf6947db /gcc/c/c-parser.cc | |
parent | 27282dc0931484c31fa391772499d878afcc746a (diff) | |
download | gcc-53d834a7fae3afffebb45a2d66908f705773a7fc.zip gcc-53d834a7fae3afffebb45a2d66908f705773a7fc.tar.gz gcc-53d834a7fae3afffebb45a2d66908f705773a7fc.tar.bz2 |
c, c++: Accept __builtin_classify_type (typename)
As mentioned in my stdckdint.h mail, __builtin_classify_type has
a problem that argument promotion (the argument is passed to ...
prototyped builtin function) means that certain type classes will
simply never appear.
I think it is too late to change how it behaves, lots of code in the
wild might rely on the current behavior.
So, the following patch adds option to use a typename rather than
expression as the operand to the builtin, making it behave similarly
to sizeof, typeof or say the clang _Generic extension where the
first argument can be there not just expression, but also typename.
I think we have other prior art here, e.g. __builtin_va_arg also
expects typename.
I've added this to both C and C++, because it would be weird if it
supported it only in C and not in C++.
2023-09-20 Jakub Jelinek <jakub@redhat.com>
gcc/
* builtins.h (type_to_class): Declare.
* builtins.cc (type_to_class): No longer static. Return
int rather than enum.
* doc/extend.texi (__builtin_classify_type): Document.
gcc/c/
* c-parser.cc (c_parser_postfix_expression_after_primary): Parse
__builtin_classify_type call with typename as argument.
gcc/cp/
* parser.cc (cp_parser_postfix_expression): Parse
__builtin_classify_type call with typename as argument.
* pt.cc (tsubst_copy_and_build): Handle __builtin_classify_type
with dependent typename as argument.
gcc/testsuite/
* c-c++-common/builtin-classify-type-1.c: New test.
* g++.dg/ext/builtin-classify-type-1.C: New test.
* g++.dg/ext/builtin-classify-type-2.C: New test.
* gcc.dg/builtin-classify-type-1.c: New test.
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r-- | gcc/c/c-parser.cc | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index b9a1b75..0d468b8 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -11606,6 +11606,29 @@ c_parser_postfix_expression_after_primary (c_parser *parser, literal_zero_mask = 0; if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) exprlist = NULL; + else if (TREE_CODE (expr.value) == FUNCTION_DECL + && fndecl_built_in_p (expr.value, BUILT_IN_CLASSIFY_TYPE) + && c_parser_next_tokens_start_typename (parser, + cla_prefer_id)) + { + /* __builtin_classify_type (type) */ + c_inhibit_evaluation_warnings++; + in_alignof++; + struct c_type_name *type = c_parser_type_name (parser); + c_inhibit_evaluation_warnings--; + in_alignof--; + struct c_typespec ret; + ret.expr = NULL_TREE; + ret.spec = error_mark_node; + ret.expr_const_operands = false; + if (type != NULL) + ret.spec = groktypename (type, &ret.expr, + &ret.expr_const_operands); + parens.skip_until_found_close (parser); + expr.value = build_int_cst (integer_type_node, + type_to_class (ret.spec)); + break; + } else exprlist = c_parser_expr_list (parser, true, false, &origtypes, sizeof_arg_loc, sizeof_arg, |