__builtin_classify_type is not returning as defined in typeclass.h

Viewed 37

I'm trying to check whether a given macro token is a pointer (__builtin_classify_type(...) == 5), but I'm running into an issue where the defined outputs of this builtin are not accurate.

After running through some tests, this is a type array I came up with (where x's are unknown/not found):

char* classes[] =  {"x"      , "integer/enum/char/long/size_t" , "x"                                  ,         
                    "x"      , "x"                             , "pointer/void/string/array/function" ,         
                    "x"      , "x"                             , "float/double"                       ,         
                    "complex", "x"                             , "x"                                  ,         
                    "struct" , "union"                         , "x"                                  ,         
                    "x"      , "x"                             , "x"                                 }; 

Compare this with the enum present in typeclass.h,

    enum type_class
    {
      no_type_class = -1,
      void_type_class, integer_type_class, char_type_class,
      enumeral_type_class, boolean_type_class,
      pointer_type_class, reference_type_class, offset_type_class,
      real_type_class, complex_type_class,
      function_type_class, method_type_class,
      record_type_class, union_type_class,
      array_type_class, string_type_class,
      lang_type_class
    };

Most of the classes I don't care about, or can't even find their definition to test (record, real, lang, etc.) My whole reasoning for using __builtin_classify_type was to identify pointers, but if it's going to also match voids, strings, arrays, and functions under the same class, then there's really no use for it.

Anyone know why __builtin_classify_type is returning values inconsistent with typeclass.h?

1 Answers

This really isn't a direct answer as to why this is happening, but more of a workaround if you are also trying to identify if a given macro token is explicitly a pointer. Unfortunately it's a bit more involved than it would be if this built-in returned the expected results.

#define is_same_type(a, b)  __builtin_types_compatible_p(typeof(a), typeof(b))

#define is_pointer_or_array(p)  __builtin_classify_type(p) == 5

char UNREACHABLE_VAR;
#define is_pointer(p) __builtin_choose_expr(is_pointer_or_array(p), \
                         is_same_type(p, &(*__builtin_choose_expr(is_pointer_or_array(p), p, &UNREACHABLE_VAR))), 0)

Using __builtin_classify_type(p), we can determine that p is either a pointer or array. Next we need to filter out any arrays, so we check to see if the entire variable p is the same type as the first element of that variable. An array would not be the same type (array vs pointer), whereas an array pointer would be the same type as the individual element. Overall, this will only return true if the token p is of pointer type.

Note: __builtin_choose_expr() is redundantly used twice with the same expression, due to the limitations of how it ignores compiler errors. We are forced to break the statement up as much as possible, so that if it returns false, the statement is still syntactically correct (even if the false branch is unreachable).

Related