aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-09-20 18:37:29 +0200
committerJakub Jelinek <jakub@redhat.com>2023-09-20 18:37:29 +0200
commit53d834a7fae3afffebb45a2d66908f705773a7fc (patch)
tree4af979256b3f85649ada1d5cabc08c21cf6947db /gcc/c/c-parser.cc
parent27282dc0931484c31fa391772499d878afcc746a (diff)
downloadgcc-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.cc23
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,