Skip to content

Commit ebf7c7e

Browse files
author
Daniel Kroening
committed
fix return values of __builtin_classify_type
1 parent 57ed2bc commit ebf7c7e

File tree

3 files changed

+41
-22
lines changed

3 files changed

+41
-22
lines changed

regression/ansi-c/gcc_builtins4/main.c

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,29 @@
22

33
#define STATIC_ASSERT(a) int __dummy__[(a)?1:-1]
44

5-
struct { int i; } s;
5+
struct { int i; _Bool bit_field : 1; } s;
66
union { int i; } u;
77
enum { Econst } e;
88
int a[10];
99

10-
STATIC_ASSERT(__builtin_classify_type(*(void *)0)==0);
1110
STATIC_ASSERT(__builtin_classify_type((int)0)==1);
12-
STATIC_ASSERT(__builtin_classify_type(e)==3);
11+
STATIC_ASSERT(__builtin_classify_type((char)0)==1);
12+
STATIC_ASSERT(__builtin_classify_type(e)==1);
13+
#ifndef __clang__
14+
STATIC_ASSERT(__builtin_classify_type((_Bool)0)==1);
15+
STATIC_ASSERT(__builtin_classify_type(s.bit_field)==1);
16+
#else
1317
STATIC_ASSERT(__builtin_classify_type((_Bool)0)==4);
18+
STATIC_ASSERT(__builtin_classify_type(s.bit_field)==4);
19+
#endif
1420
STATIC_ASSERT(__builtin_classify_type((int *)0)==5);
1521
STATIC_ASSERT(__builtin_classify_type(1.0)==8);
1622
STATIC_ASSERT(__builtin_classify_type(*(0?(void *)0:(double *)0))==8);
1723
STATIC_ASSERT(__builtin_classify_type(*(0?(double *)0:(void *)0))==8);
1824
STATIC_ASSERT(__builtin_classify_type((_Complex double)0)==9);
1925
STATIC_ASSERT(__builtin_classify_type(s)==12);
2026
STATIC_ASSERT(__builtin_classify_type(u)==13);
21-
STATIC_ASSERT(__builtin_classify_type(a)==14);
27+
STATIC_ASSERT(__builtin_classify_type(a)==5);
2228

2329
#endif
2430

regression/ansi-c/gcc_builtins4/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE gcc-only
22
main.c
33

44
^EXIT=0$

src/ansi-c/c_typecheck_expr.cpp

+30-17
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/arith_tools.h>
1717
#include <util/base_type.h>
1818
#include <util/c_types.h>
19+
#include <util/config.h>
1920
#include <util/cprover_prefix.h>
2021
#include <util/ieee_float.h>
2122
#include <util/pointer_offset_size.h>
@@ -2581,7 +2582,7 @@ exprt c_typecheck_baset::do_special_functions(
25812582
}
25822583
else if(identifier=="__builtin_classify_type")
25832584
{
2584-
// This is a gcc extension that produces an integer
2585+
// This is a gcc/clang extension that produces an integer
25852586
// constant for the type of the argument expression.
25862587
if(expr.arguments().size()!=1)
25872588
{
@@ -2594,22 +2595,34 @@ exprt c_typecheck_baset::do_special_functions(
25942595

25952596
// The value doesn't matter at all, we only care about the type.
25962597
// Need to sync with typeclass.h.
2597-
const typet &type=follow(object.type());
2598-
2599-
unsigned type_number=
2600-
type.id()==ID_empty?0:
2601-
type.id()==ID_c_enum_tag?3:
2602-
(type.id()==ID_bool || type.id()==ID_c_bool)?4:
2603-
type.id()==ID_pointer?5:
2604-
type.id()==ID_floatbv?8:
2605-
(type.id()==ID_complex && type.subtype().id()==ID_floatbv)?9:
2606-
type.id()==ID_struct?12:
2607-
type.id()==ID_union?13:
2608-
type.id()==ID_array?14:
2609-
1; // int, short
2610-
2611-
// clang returns 15 for the three 'char' types,
2612-
// gcc treats these as 'int'
2598+
typet type = follow(object.type());
2599+
2600+
// use underlying type for bit fields
2601+
if(type.id() == ID_c_bit_field)
2602+
type = to_c_bit_field_type(type).subtype();
2603+
2604+
unsigned type_number;
2605+
2606+
if(type.id() == ID_bool || type.id() == ID_c_bool)
2607+
{
2608+
// clang returns 4 for _Bool, gcc treats these as 'int'.
2609+
type_number =
2610+
config.ansi_c.preprocessor == configt::ansi_ct::preprocessort::CLANG
2611+
? 4
2612+
: 1;
2613+
}
2614+
else
2615+
{
2616+
type_number =
2617+
type.id() == ID_empty ? 0
2618+
: (type.id() == ID_bool || type.id() == ID_c_bool) ? 4
2619+
: (type.id() == ID_pointer || type.id() == ID_array) ? 5
2620+
: type.id() == ID_floatbv ? 8
2621+
: (type.id() == ID_complex && type.subtype().id() == ID_floatbv) ? 9
2622+
: type.id() == ID_struct ? 12
2623+
: type.id() == ID_union ? 13
2624+
: 1; // int, short, char, enum_tag
2625+
}
26132626

26142627
exprt tmp=from_integer(type_number, expr.type());
26152628
tmp.add_source_location()=source_location;

0 commit comments

Comments
 (0)