public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Jason Merrill <jason@redhat.com>,
	"Joseph S. Myers" <joseph@codesourcery.com>,
	Marek Polacek <polacek@redhat.com>,
	gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c, c++, v2: Accept __builtin_classify_type (typename)
Date: Fri, 11 Aug 2023 10:48:19 +0200	[thread overview]
Message-ID: <ZNX100n2YImOMOm4@tucnak> (raw)
In-Reply-To: <ZNVvGoydjvu3FZyC@tucnak>

On Fri, Aug 11, 2023 at 01:13:32AM +0200, Jakub Jelinek wrote:
> Looking at the first uses of the builtin back in 90s in va*.h, it certainly
> relied on array/function decay there (the macros would abort e.g. on
> array_type_class, function_type_class and various other return values).
> Looking at older versions of tgmath.h, I see just checks for 8/9 (i.e.
> real/complex) and those woiuldn't be affected by any promotions/decay.
> But newer versions of tgmath.h before __builtin_tgmath do check also for
> 1 and they would be upset if char wasn't promoted to int (including latest
> glibc).
> systemtap macros also use __builtin_classify_type and do check for pointers
> but those seems to be prepared to handle even arrays.

So to sum it up, I think at least the original use of the builtin had a
strong reason to do the array to pointer etc. decay and argument promotion,
because that is what happens with the varargs too and the builtin is still
documented in the internals manual just for that purpose.  It is true GCC
doesn't use the builtin for that reason anymore, but there are numerous
uses in the wild, some might cope well with changing the behavior, others
less so.

> > > +		cp_evaluated ev;
> > > +		++cp_unevaluated_operand;
> > > +		++c_inhibit_evaluation_warnings;
> > 
> > These three lines seem unnecessary for parsing a type.

I had a quick look at this and a reason to do at least some of this
is e.g. array types, __builtin_classify_type (int [foo () + whatever])
will not really evaluate foo () + whatever, all it will care about is that
it is an array, so emiting evaluation warnings for it would be weird.
cp_unevaluated_operand is harder to find out what all the effects are,
but e.g. warnings for missing member initializers in such expressions
isn't needed either.

> > > +		tentative_firewall firewall (parser);
> > 
> > I think you only need a tentative_firewall if you're going to call
> > cp_parser_commit_to_tentative_parse yourself, which you don't.
> 
> I think I've just copied this from elsewhere, will double check in the
> morning which ones aren't really needed.

I admit I still don't understand match what it is doing, but it works
even without that in the limited testsuite coverage it has.

2023-08-11  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.

--- gcc/builtins.h.jj	2023-01-03 00:20:34.856089856 +0100
+++ gcc/builtins.h	2023-06-12 09:35:20.841902572 +0200
@@ -156,5 +156,6 @@ extern internal_fn associated_internal_f
 extern internal_fn replacement_internal_fn (gcall *);
 
 extern bool builtin_with_linkage_p (tree);
+extern int type_to_class (tree);
 
 #endif /* GCC_BUILTINS_H */
--- gcc/builtins.cc.jj	2023-05-20 15:31:09.066663352 +0200
+++ gcc/builtins.cc	2023-06-12 09:35:31.709751296 +0200
@@ -113,7 +113,6 @@ static rtx expand_builtin_apply_args (vo
 static rtx expand_builtin_apply_args_1 (void);
 static rtx expand_builtin_apply (rtx, rtx, rtx);
 static void expand_builtin_return (rtx);
-static enum type_class type_to_class (tree);
 static rtx expand_builtin_classify_type (tree);
 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx);
@@ -1852,7 +1851,7 @@ expand_builtin_return (rtx result)
 
 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
 
-static enum type_class
+int
 type_to_class (tree type)
 {
   switch (TREE_CODE (type))
--- gcc/doc/extend.texi.jj	2023-06-10 19:58:26.197478291 +0200
+++ gcc/doc/extend.texi	2023-06-12 18:06:24.629413024 +0200
@@ -14354,6 +14354,30 @@ need not be a constant.  @xref{Object Si
 description of the function.
 @enddefbuiltin
 
+@defbuiltin{int __builtin_classify_type (@var{arg})}
+@defbuiltinx{int __builtin_classify_type (@var{type})}
+The @code{__builtin_classify_type} returns a small integer with a category
+of @var{arg} argument's type, like void type, integer type, enumeral type,
+boolean type, pointer type, reference type, offset type, real type, complex
+type, function type, method type, record type, union type, array type,
+string type, etc.  When the argument is an expression, for
+backwards compatibility reason the argument is promoted like arguments
+passed to @code{...} in varargs function, so some classes are never returned
+in certain languages.  Alternatively, the argument of the built-in
+function can be a typename, such as the @code{typeof} specifier.
+
+@smallexample
+int a[2];
+__builtin_classify_type (a) == __builtin_classify_type (int[5]);
+__builtin_classify_type (a) == __builtin_classify_type (void*);
+__builtin_classify_type (typeof (a)) == __builtin_classify_type (int[5]);
+@end smallexample
+
+The first comparison will never be true, as @var{a} is implicitly converted
+to pointer.  The last two comparisons will be true as they classify
+pointers in the second case and arrays in the last case.
+@enddefbuiltin
+
 @defbuiltin{double __builtin_huge_val (void)}
 Returns a positive infinity, if supported by the floating-point format,
 else @code{DBL_MAX}.  This function is suitable for implementing the
--- gcc/c/c-parser.cc.jj	2023-06-10 19:22:15.577205685 +0200
+++ gcc/c/c-parser.cc	2023-06-12 17:32:31.007413019 +0200
@@ -11213,6 +11213,32 @@ c_parser_postfix_expression_after_primar
 	    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_typeof++;
+		struct c_type_name *type = c_parser_type_name (parser);
+		c_inhibit_evaluation_warnings--;
+		in_typeof--;
+		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);
+		    pop_maybe_used (c_type_variably_modified_p (ret.spec));
+		  }
+		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,
--- gcc/cp/parser.cc.jj	2023-06-06 20:02:35.631211230 +0200
+++ gcc/cp/parser.cc	2023-06-12 16:19:04.892202240 +0200
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.
 #include "c-family/known-headers.h"
 #include "contracts.h"
 #include "bitmap.h"
+#include "builtins.h"
 
 \f
 /* The lexer.  */
@@ -7850,6 +7851,49 @@ cp_parser_postfix_expression (cp_parser
 		  = parser->non_integral_constant_expression_p;
 		parser->integral_constant_expression_p = false;
 	      }
+	    else if (TREE_CODE (stripped_expression) == FUNCTION_DECL
+		     && fndecl_built_in_p (stripped_expression,
+					   BUILT_IN_CLASSIFY_TYPE))
+	      {
+		/* __builtin_classify_type (type)  */
+		auto cl1 = make_temp_override
+			     (parser->type_definition_forbidden_message,
+			      G_("types may not be defined in "
+				 "%<__builtin_classify_type%> calls"));
+		auto cl2 = make_temp_override
+			     (parser->type_definition_forbidden_message_arg,
+			      NULL);
+		auto cl3 = make_temp_override (parser->in_type_id_in_expr_p,
+					       true);
+		cp_evaluated ev;
+		++cp_unevaluated_operand;
+		++c_inhibit_evaluation_warnings;
+		cp_parser_parse_tentatively (parser);
+		matching_parens parens;
+		parens.consume_open (parser);
+		tree type = cp_parser_type_id (parser);
+		parens.require_close (parser);
+		if (cp_parser_parse_definitely (parser))
+		  {
+		    if (dependent_type_p (type))
+		      {
+			postfix_expression = build_vl_exp (CALL_EXPR, 4);
+			CALL_EXPR_FN (postfix_expression)
+			  = stripped_expression;
+			CALL_EXPR_STATIC_CHAIN (postfix_expression) = type;
+			CALL_EXPR_ARG (postfix_expression, 0)
+			  = build_min (SIZEOF_EXPR, size_type_node, type);
+			TREE_TYPE (postfix_expression) = integer_type_node;
+		      }
+		    else
+		      {
+			postfix_expression
+			  = build_int_cst (integer_type_node,
+					   type_to_class (type));
+		      }
+		    break;
+		  }
+	      }
 	    args = (cp_parser_parenthesized_expression_list
 		    (parser, non_attr,
 		     /*cast_p=*/false, /*allow_expansion_p=*/true,
--- gcc/cp/pt.cc.jj	2023-06-06 20:02:35.000000000 +0200
+++ gcc/cp/pt.cc	2023-06-12 16:19:06.495180108 +0200
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.
 #include "gcc-rich-location.h"
 #include "selftest.h"
 #include "target.h"
+#include "builtins.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -20963,6 +20964,25 @@ tsubst_copy_and_build (tree t,
 					    /*done=*/false,
 					    /*address_p=*/false);
 	  }
+	else if (CALL_EXPR_STATIC_CHAIN (t)
+		 && TREE_CODE (function) == FUNCTION_DECL
+		 && fndecl_built_in_p (function, BUILT_IN_CLASSIFY_TYPE))
+	  {
+	    tree type = tsubst (CALL_EXPR_STATIC_CHAIN (t), args, complain,
+				in_decl);
+	    if (dependent_type_p (type))
+	      {
+		ret = build_vl_exp (CALL_EXPR, 4);
+		CALL_EXPR_FN (ret) = function;
+		CALL_EXPR_STATIC_CHAIN (ret) = type;
+		CALL_EXPR_ARG (ret, 0)
+		  = build_min (SIZEOF_EXPR, size_type_node, type);
+		TREE_TYPE (ret) = integer_type_node;
+	      }
+	    else
+	      ret = build_int_cst (integer_type_node, type_to_class (type));
+	    RETURN (ret);
+	  }
 	else if (koenig_p
 		 && (identifier_p (function)
 		     || (TREE_CODE (function) == TEMPLATE_ID_EXPR
--- gcc/testsuite/c-c++-common/builtin-classify-type-1.c.jj	2023-06-12 14:27:19.087986210 +0200
+++ gcc/testsuite/c-c++-common/builtin-classify-type-1.c	2023-06-12 16:23:07.029859079 +0200
@@ -0,0 +1,105 @@
+/* { dg-do run { target { c || c++11 } } } */
+
+#if !defined(__cplusplus) && __STDC_VERSION__ <= 201710L
+#define static_assert _Static_assert
+#define bool _Bool
+#define false ((_Bool) 0)
+#endif
+#ifdef __cplusplus
+extern "C" void abort ();
+#else
+extern void abort (void);
+#endif
+
+int
+main ()
+{
+  enum E { E1 } e = E1;
+  struct S { int s; } s = { 0 };
+  union U { int u; } u = { 0 };
+  int a[2] = { 0, 0 };
+  bool b = false;
+  const char *p = (const char *) 0;
+  float f = 0.0;
+  _Complex double c = 0.0;
+#ifdef __cplusplus
+  struct T { void foo (); };
+  int &r = a[0];
+  int S::*q = &S::s;
+#endif
+  static_assert (__builtin_classify_type (void) == 0, "");
+  static_assert (__builtin_classify_type (int) == 1, "");
+  static_assert (__builtin_classify_type (enum E) == 3, "");
+  static_assert (__builtin_classify_type (bool) == 4, "");
+  static_assert (__builtin_classify_type (const char *) == 5, "");
+#ifdef __cplusplus
+  static_assert (__builtin_classify_type (int &) == 6, "");
+  static_assert (__builtin_classify_type (int &&) == 6, "");
+  static_assert (__builtin_classify_type (int S::*) == 7, "");
+#endif
+  static_assert (__builtin_classify_type (float) == 8, "");
+  static_assert (__builtin_classify_type (_Complex double) == 9, "");
+  static_assert (__builtin_classify_type (int (int, int)) == 10, "");
+  static_assert (__builtin_classify_type (struct S) == 12, "");
+  static_assert (__builtin_classify_type (union U) == 13, "");
+  static_assert (__builtin_classify_type (int [2]) == 14, "");
+  static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, "");
+  static_assert (__builtin_classify_type (__typeof__ (e)) == 3, "");
+  static_assert (__builtin_classify_type (__typeof__ (b)) == 4, "");
+  static_assert (__builtin_classify_type (__typeof__ (p)) == 5, "");
+#ifdef __cplusplus
+  static_assert (__builtin_classify_type (decltype (r)) == 6, "");
+  static_assert (__builtin_classify_type (__typeof__ (q)) == 7, "");
+#endif
+  static_assert (__builtin_classify_type (__typeof__ (f)) == 8, "");
+  static_assert (__builtin_classify_type (__typeof__ (c)) == 9, "");
+  static_assert (__builtin_classify_type (__typeof__ (main)) == 10, "");
+  static_assert (__builtin_classify_type (__typeof__ (s)) == 12, "");
+  static_assert (__builtin_classify_type (__typeof__ (u)) == 13, "");
+  static_assert (__builtin_classify_type (__typeof__ (a)) == 14, "");
+#ifndef __cplusplus
+  static_assert (__builtin_classify_type (a[0]) == 1, "");
+  static_assert (__builtin_classify_type (e) == 1, "");
+  static_assert (__builtin_classify_type (b) == 1, "");
+  static_assert (__builtin_classify_type (p) == 5, "");
+  static_assert (__builtin_classify_type (f) == 8, "");
+  static_assert (__builtin_classify_type (c) == 9, "");
+  static_assert (__builtin_classify_type (main) == 5, "");
+  static_assert (__builtin_classify_type (s) == 12, "");
+  static_assert (__builtin_classify_type (u) == 13, "");
+  static_assert (__builtin_classify_type (a) == 5, "");
+#endif
+  if (__builtin_classify_type (a[0]) != 1)
+    abort ();
+#ifdef __cplusplus
+  if (__builtin_classify_type (e) != 3)
+    abort ();
+  if (__builtin_classify_type (b) != 4)
+    abort ();
+#else
+  if (__builtin_classify_type (e) != 1)
+    abort ();
+  if (__builtin_classify_type (b) != 1)
+    abort ();
+#endif
+  if (__builtin_classify_type (p) != 5)
+    abort ();
+#ifdef __cplusplus
+  if (__builtin_classify_type (r) != 1)
+    abort ();
+  if (__builtin_classify_type (q) != 7)
+    abort ();
+#endif
+  if (__builtin_classify_type (f) != 8)
+    abort ();
+  if (__builtin_classify_type (c) != 9)
+    abort ();
+  if (__builtin_classify_type (main) != 5)
+    abort ();
+  if (__builtin_classify_type (s) != 12)
+    abort ();
+  if (__builtin_classify_type (u) != 13)
+    abort ();
+  if (__builtin_classify_type (a) != 5)
+    abort ();
+}
--- gcc/testsuite/g++.dg/ext/builtin-classify-type-1.C.jj	2023-06-12 15:03:37.488813774 +0200
+++ gcc/testsuite/g++.dg/ext/builtin-classify-type-1.C	2023-06-12 16:24:17.787882132 +0200
@@ -0,0 +1,149 @@
+// { dg-do run { target c++11 } }
+
+extern "C" void abort ();
+
+template <int N>
+void
+foo ()
+{
+  enum E { E1 } e = E1;
+  struct S { int s; } s = { 0 };
+  union U { int u; } u = { 0 };
+  int a[2] = { 0, 0 };
+  bool b = false;
+  const char *p = (const char *) 0;
+  float f = 0.0;
+  _Complex double c = 0.0;
+  struct T { void foo (); };
+  int &r = a[0];
+  int S::*q = &S::s;
+  static_assert (__builtin_classify_type (void) == 0, "");
+  static_assert (__builtin_classify_type (int) == 1, "");
+  static_assert (__builtin_classify_type (enum E) == 3, "");
+  static_assert (__builtin_classify_type (bool) == 4, "");
+  static_assert (__builtin_classify_type (const char *) == 5, "");
+  static_assert (__builtin_classify_type (int &) == 6, "");
+  static_assert (__builtin_classify_type (int &&) == 6, "");
+  static_assert (__builtin_classify_type (int S::*) == 7, "");
+  static_assert (__builtin_classify_type (float) == 8, "");
+  static_assert (__builtin_classify_type (_Complex double) == 9, "");
+  static_assert (__builtin_classify_type (int (int, int)) == 10, "");
+  static_assert (__builtin_classify_type (struct S) == 12, "");
+  static_assert (__builtin_classify_type (union U) == 13, "");
+  static_assert (__builtin_classify_type (int [2]) == 14, "");
+  static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, "");
+  static_assert (__builtin_classify_type (__typeof__ (e)) == 3, "");
+  static_assert (__builtin_classify_type (__typeof__ (b)) == 4, "");
+  static_assert (__builtin_classify_type (__typeof__ (p)) == 5, "");
+  static_assert (__builtin_classify_type (decltype (r)) == 6, "");
+  static_assert (__builtin_classify_type (__typeof__ (q)) == 7, "");
+  static_assert (__builtin_classify_type (__typeof__ (f)) == 8, "");
+  static_assert (__builtin_classify_type (__typeof__ (c)) == 9, "");
+  static_assert (__builtin_classify_type (__typeof__ (abort)) == 10, "");
+  static_assert (__builtin_classify_type (__typeof__ (s)) == 12, "");
+  static_assert (__builtin_classify_type (__typeof__ (u)) == 13, "");
+  static_assert (__builtin_classify_type (__typeof__ (a)) == 14, "");
+  if (__builtin_classify_type (a[0]) != 1)
+    abort ();
+  if (__builtin_classify_type (e) != 3)
+    abort ();
+  if (__builtin_classify_type (b) != 4)
+    abort ();
+  if (__builtin_classify_type (p) != 5)
+    abort ();
+  if (__builtin_classify_type (r) != 1)
+    abort ();
+  if (__builtin_classify_type (q) != 7)
+    abort ();
+  if (__builtin_classify_type (f) != 8)
+    abort ();
+  if (__builtin_classify_type (c) != 9)
+    abort ();
+  if (__builtin_classify_type (abort) != 5)
+    abort ();
+  if (__builtin_classify_type (s) != 12)
+    abort ();
+  if (__builtin_classify_type (u) != 13)
+    abort ();
+  if (__builtin_classify_type (a) != 5)
+    abort ();
+}
+
+template <typename V, typename I, typename E, typename B, typename P,
+	  typename R1, typename R2, typename PM, typename F,
+	  typename C, typename FN, typename S, typename U, typename A>
+void
+bar ()
+{
+  E e = (E) 0;
+  S s = { 0 };
+  U u = { 0 };
+  A a = { 0, 0 };
+  B b = false;
+  P p = (P) 0;
+  F f = 0.0;
+  C c = 0.0;
+  R1 r = a[0];
+  PM q = &S::s;
+  static_assert (__builtin_classify_type (V) == 0, "");
+  static_assert (__builtin_classify_type (I) == 1, "");
+  static_assert (__builtin_classify_type (E) == 3, "");
+  static_assert (__builtin_classify_type (B) == 4, "");
+  static_assert (__builtin_classify_type (P) == 5, "");
+  static_assert (__builtin_classify_type (R1) == 6, "");
+  static_assert (__builtin_classify_type (R2) == 6, "");
+  static_assert (__builtin_classify_type (PM) == 7, "");
+  static_assert (__builtin_classify_type (F) == 8, "");
+  static_assert (__builtin_classify_type (C) == 9, "");
+  static_assert (__builtin_classify_type (FN) == 10, "");
+  static_assert (__builtin_classify_type (S) == 12, "");
+  static_assert (__builtin_classify_type (U) == 13, "");
+  static_assert (__builtin_classify_type (A) == 14, "");
+  static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, "");
+  static_assert (__builtin_classify_type (__typeof__ (e)) == 3, "");
+  static_assert (__builtin_classify_type (__typeof__ (b)) == 4, "");
+  static_assert (__builtin_classify_type (__typeof__ (p)) == 5, "");
+  static_assert (__builtin_classify_type (decltype (r)) == 6, "");
+  static_assert (__builtin_classify_type (__typeof__ (q)) == 7, "");
+  static_assert (__builtin_classify_type (__typeof__ (f)) == 8, "");
+  static_assert (__builtin_classify_type (__typeof__ (c)) == 9, "");
+  static_assert (__builtin_classify_type (__typeof__ (abort)) == 10, "");
+  static_assert (__builtin_classify_type (__typeof__ (s)) == 12, "");
+  static_assert (__builtin_classify_type (__typeof__ (u)) == 13, "");
+  static_assert (__builtin_classify_type (__typeof__ (a)) == 14, "");
+  if (__builtin_classify_type (a[0]) != 1)
+    abort ();
+  if (__builtin_classify_type (e) != 3)
+    abort ();
+  if (__builtin_classify_type (b) != 4)
+    abort ();
+  if (__builtin_classify_type (p) != 5)
+    abort ();
+  if (__builtin_classify_type (r) != 1)
+    abort ();
+  if (__builtin_classify_type (q) != 7)
+    abort ();
+  if (__builtin_classify_type (f) != 8)
+    abort ();
+  if (__builtin_classify_type (c) != 9)
+    abort ();
+  if (__builtin_classify_type (abort) != 5)
+    abort ();
+  if (__builtin_classify_type (s) != 12)
+    abort ();
+  if (__builtin_classify_type (u) != 13)
+    abort ();
+  if (__builtin_classify_type (a) != 5)
+    abort ();
+}
+
+int
+main ()
+{
+  enum E { E1 };
+  struct S { int s; };
+  union U { int u; };
+  foo <0> ();
+  bar <void, int, E, bool, const char *, int &, int &&, int S::*,
+       float, _Complex double, int (int, int), S, U, int [2]> ();
+}
--- gcc/testsuite/g++.dg/ext/builtin-classify-type-2.C.jj	2023-06-12 16:28:17.120577700 +0200
+++ gcc/testsuite/g++.dg/ext/builtin-classify-type-2.C	2023-06-12 16:29:57.860186807 +0200
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+void
+foo (int n)
+{
+  __builtin_classify_type (enum E { E1, E2 });	// { dg-error "types may not be defined in '__builtin_classify_type' calls" }
+  __builtin_classify_type (struct S { int s; });// { dg-error "types may not be defined in '__builtin_classify_type' calls" }
+  __builtin_classify_type (union U { int u; });	// { dg-error "types may not be defined in '__builtin_classify_type' calls" }
+  __builtin_classify_type (int [2 * n + 36]);
+}
--- gcc/testsuite/gcc.dg/builtin-classify-type-1.c.jj	2023-06-12 17:28:47.118495177 +0200
+++ gcc/testsuite/gcc.dg/builtin-classify-type-1.c	2023-06-12 17:43:46.420114514 +0200
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+foo (int n)
+{
+  _Static_assert (__builtin_classify_type (enum E { E1, E2 }) == 3, "");
+  _Static_assert (__builtin_classify_type (struct S { int s; }) == 12, "");
+  _Static_assert (__builtin_classify_type (union U { int u; }) == 13, "");
+  _Static_assert (__builtin_classify_type (int [2 * n + 36]) == 14, "");
+}


	Jakub


  reply	other threads:[~2023-08-11  8:48 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-12 19:57 [PATCH] c, c++: " Jakub Jelinek
2023-06-13  8:48 ` Jason Merrill
2023-08-10 15:35 ` [PATCH] c, c++, v2: " Jakub Jelinek
2023-08-10 21:44   ` Jason Merrill
2023-08-10 22:27     ` Joseph Myers
2023-08-10 23:13     ` Jakub Jelinek
2023-08-11  8:48       ` Jakub Jelinek [this message]
2023-08-11 16:12         ` Jason Merrill
2023-09-18  9:42         ` Patch ping: " Jakub Jelinek
2023-09-18 21:25           ` Joseph Myers
2023-09-20  7:17             ` [PATCH] c, c++, v3: " Jakub Jelinek
2023-09-20 16:08               ` Joseph Myers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZNX100n2YImOMOm4@tucnak \
    --to=jakub@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    --cc=joseph@codesourcery.com \
    --cc=polacek@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).