On Sat, 7 Jul 2007, Joseph S. Myers wrote:

> On Sat, 7 Jul 2007, Kaveh R. GHAZI wrote:
>
> > Ok, how about e.g. __attribute__ ((__type_generic__)), which would only be
> > allowed on variadic functions?
>
> I don't think we want this available to user code, just to builtins, so a
> name such as "type generic" that can't be used as an identifier would be
> better (see "no vops" for an existing example).

Ok, here's a patch which adds the attribute named as you suggest and
applies it to the relevant builtins.  I'm stuck now on how and where we
would intervene to honor it.  I think we need to do it in c-decl.c:
grokdeclarator(), where it says "promoted_type = c_type_promotes_to(type)"
around line 4757.  However I'm not sure if we have a handle on the
function decl and it's attributes here to know when to do it.  Some help
would be appreciated.

                Thanks,
                --Kaveh



diff -rup orig/egcc-SVN20070706/gcc/builtin-attrs.def 
egcc-SVN20070706/gcc/builtin-attrs.def
--- orig/egcc-SVN20070706/gcc/builtin-attrs.def 2006-01-23 00:24:01.000000000 
-0500
+++ egcc-SVN20070706/gcc/builtin-attrs.def      2007-07-07 17:25:40.785175001 
-0400
@@ -94,6 +94,7 @@ DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
 DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
 DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
 DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
+DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic")

 DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)

@@ -142,6 +143,9 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL
 /* Nothrow const functions whose pointer parameter(s) are all nonnull.  */
 DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL, ATTR_CONST, ATTR_NULL, \
                        ATTR_NOTHROW_NONNULL)
+/* Nothrow const functions which are type-generic.  */
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_TYPEGENERIC, ATTR_TYPEGENERIC, 
ATTR_NULL, \
+                       ATTR_CONST_NOTHROW_LIST)
 /* Nothrow pure functions whose pointer parameter(s) are all nonnull.  */
 DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL, ATTR_PURE, ATTR_NULL, \
                        ATTR_NOTHROW_NONNULL)
diff -rup orig/egcc-SVN20070706/gcc/builtins.def 
egcc-SVN20070706/gcc/builtins.def
--- orig/egcc-SVN20070706/gcc/builtins.def      2007-05-17 23:03:49.000000000 
-0400
+++ egcc-SVN20070706/gcc/builtins.def   2007-07-07 13:06:50.789804475 -0400
@@ -653,24 +653,24 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITEL
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITED64, "finited64", BT_FN_INT_DFLOAT64, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITED128, "finited128", 
BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
-DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFF, "isinff", BT_FN_INT_FLOAT, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFD32, "isinfd32", BT_FN_INT_DFLOAT32, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFD64, "isinfd64", BT_FN_INT_DFLOAT64, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFD128, "isinfd128", BT_FN_INT_DFLOAT128, 
ATTR_CONST_NOTHROW_LIST)
-DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, 
ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, 
ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", 
BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISLESSGREATER, "islessgreater", 
BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", 
BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISLESSGREATER, "islessgreater", 
BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, 
ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_LIB_BUILTIN        (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, 
ATTR_CONST_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, 
ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, 
ATTR_NORETURN_NOTHROW_LIST)
diff -rup orig/egcc-SVN20070706/gcc/c-common.c egcc-SVN20070706/gcc/c-common.c
--- orig/egcc-SVN20070706/gcc/c-common.c        2007-07-06 23:02:59.000000000 
-0400
+++ egcc-SVN20070706/gcc/c-common.c     2007-07-07 17:46:59.071601490 -0400
@@ -555,6 +555,7 @@ static tree handle_cleanup_attribute (tr
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
                                                 bool *);
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);

 static void check_function_nonnull (tree, int, tree *);
@@ -650,6 +651,10 @@ const struct attribute_spec c_common_att
                              handle_warn_unused_result_attribute },
   { "sentinel",               0, 1, false, true, true,
                              handle_sentinel_attribute },
+  /* For internal use (marking of builtins) only.  The name contains space
+     to prevent its usage in source code.  */
+  { "type generic",           0, 0, false, true, true,
+                             handle_type_generic_attribute },
   { "alloc_size",            1, 2, false, true, true,
                              handle_alloc_size_attribute },
   { "cold",                   0, 0, true,  false, false,
@@ -6154,6 +6159,18 @@ handle_sentinel_attribute (tree *node, t

   return NULL_TREE;
 }
+
+/* Handle a "type_generic" attribute.  */
+
+static tree
+handle_type_generic_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+                              int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  /* Ensure we have a function type, with no arguments.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE && ! TYPE_ARG_TYPES (*node));
+
+  return NULL_TREE;
+}

 /* Check for valid arguments being passed to a function.
    ATTRS is a list of attributes.  There are NARGS arguments in the array

Reply via email to