2014-01-16 10:37:08 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify %s
2009-04-30 06:16:16 +08:00
typedef union {
int * ip ;
float * fp ;
2010-12-03 04:02:29 +08:00
long * __restrict rlp ;
2010-12-03 05:00:06 +08:00
void * vpa [ 1 ] ;
2009-04-30 06:16:16 +08:00
} TU __attribute__ ( ( transparent_union ) ) ;
2010-04-22 08:20:18 +08:00
void f ( TU ) ; // expected-note{{passing argument to parameter here}}
2009-04-30 06:16:16 +08:00
void g ( int * ip , float * fp , char * cp ) {
f ( ip ) ;
f ( fp ) ;
f ( cp ) ; // expected-error{{incompatible type}}
f ( 0 ) ;
TU tu_ip = ip ; // expected-error{{incompatible type}}
TU tu ;
tu . ip = ip ;
}
2010-10-25 02:30:18 +08:00
/* Test ability to redeclare a function taking a transparent_union arg
with various compatible and incompatible argument types . */
void fip ( TU ) ;
void fip ( int * i ) { }
void ffp ( TU ) ;
void ffp ( float * f ) { }
2010-12-03 04:02:29 +08:00
void flp ( TU ) ;
void flp ( long * l ) { }
2010-10-25 02:30:18 +08:00
void fvp ( TU ) ; // expected-note{{previous declaration is here}}
void fvp ( void * p ) { } // expected-error{{conflicting types}}
void fsp ( TU ) ; // expected-note{{previous declaration is here}}
void fsp ( short * s ) { } // expected-error{{conflicting types}}
void fi ( TU ) ; // expected-note{{previous declaration is here}}
void fi ( int i ) { } // expected-error{{conflicting types}}
2010-12-03 05:00:06 +08:00
void fvpp ( TU ) ; // expected-note{{previous declaration is here}}
void fvpp ( void * * v ) { } // expected-error{{conflicting types}}
2018-01-23 06:29:24 +08:00
/* Test redeclaring a function taking a transparent_union arg more than twice.
Merging different declarations depends on their order , vary order too . */
void f_triple0 ( TU tu ) { }
void f_triple0 ( int * ) ; // expected-note{{previous declaration is here}}
void f_triple0 ( float * f ) ; // expected-error{{conflicting types}}
void f_triple1 ( int * ) ;
void f_triple1 ( TU tu ) { } // expected-note{{previous definition is here}}
void f_triple1 ( float * f ) ; // expected-error{{conflicting types}}
void f_triple2 ( int * ) ; // expected-note{{previous declaration is here}}
void f_triple2 ( float * f ) ; // expected-error{{conflicting types}}
void f_triple2 ( TU tu ) { }
/* Test calling redeclared function taking a transparent_union arg. */
void f_callee ( TU ) ;
void f_callee ( int * i ) { } // expected-note{{passing argument to parameter 'i' here}}
void caller ( void ) {
TU tu ;
f_callee ( tu ) ; // expected-error{{passing 'TU' to parameter of incompatible type 'int *'}}
int * i ;
f_callee ( i ) ;
}
2009-04-30 06:16:16 +08:00
/* FIXME: we'd like to just use an "int" here and align it differently
from the normal " int " , but if we do so we lose the alignment
information from the typedef within the compiler . */
typedef struct { int x , y ; } __attribute__ ( ( aligned ( 8 ) ) ) aligned_struct8 ;
typedef struct { int x , y ; } __attribute__ ( ( aligned ( 4 ) ) ) aligned_struct4 ;
typedef union {
aligned_struct4 s4 ; // expected-note{{alignment of first field}}
aligned_struct8 s8 ; // expected-warning{{alignment of field}}
} TU1 __attribute__ ( ( transparent_union ) ) ;
2017-03-01 04:44:39 +08:00
typedef union __attribute__ ( ( transparent_union ) ) {
aligned_struct4 s4 ; // expected-note{{alignment of first field}}
aligned_struct8 s8 ; // expected-warning{{alignment of field}}
} TU1b ;
2009-04-30 06:16:16 +08:00
typedef union {
char c ; // expected-note{{size of first field is 8 bits}}
int i ; // expected-warning{{size of field}}
} TU2 __attribute__ ( ( transparent_union ) ) ;
2017-03-01 04:44:39 +08:00
typedef union __attribute__ ( ( transparent_union ) ) {
char c ; // expected-note{{size of first field is 8 bits}}
int i ; // expected-warning{{size of field}}
} TU2b ;
2009-04-30 06:16:16 +08:00
typedef union {
float f ; // expected-warning{{floating}}
} TU3 __attribute__ ( ( transparent_union ) ) ;
typedef union { } TU4 __attribute__ ( ( transparent_union ) ) ; // expected-warning{{field}}
2010-07-01 01:24:13 +08:00
typedef int int4 __attribute__ ( ( ext_vector_type ( 4 ) ) ) ;
typedef union {
2014-04-26 04:41:38 +08:00
int4 vec ; // expected-warning{{first field of a transparent union cannot have vector type 'int4' (vector of 4 'int' values); transparent_union attribute ignored}}
2010-07-01 01:24:13 +08:00
} TU5 __attribute__ ( ( transparent_union ) ) ;
2014-01-28 09:47:34 +08:00
union pr15134 {
unsigned int u ;
struct {
unsigned int expo : 2 ;
unsigned int mant : 30 ;
} __attribute__ ( ( packed ) ) ;
// The packed attribute is acceptable because it defines a less strict
// alignment than required by the first field of the transparent union.
} __attribute__ ( ( transparent_union ) ) ;
union pr15134v2 {
struct { // expected-note {{alignment of first field is 32 bits}}
unsigned int u1 ;
unsigned int u2 ;
} ;
struct { // expected-warning {{alignment of field '' (64 bits) does not match the alignment of the first field in transparent union; transparent_union attribute ignored}}
unsigned int u3 ;
} __attribute__ ( ( aligned ( 8 ) ) ) ;
} __attribute__ ( ( transparent_union ) ) ;
2016-10-06 17:47:29 +08:00
union pr30520v { void b ; } __attribute__ ( ( transparent_union ) ) ; // expected-error {{field has incomplete type 'void'}}
2017-10-24 06:01:41 +08:00
union pr30520a { int b [ ] ; } __attribute__ ( ( transparent_union ) ) ; // expected-error {{flexible array member 'b' in a union is not allowed}}
2016-10-06 17:47:29 +08:00
// expected-note@+1 2 {{forward declaration of 'struct stb'}}
union pr30520s { struct stb b ; } __attribute__ ( ( transparent_union ) ) ; // expected-error {{field has incomplete type 'struct stb'}}
union pr30520s2 { int * v ; struct stb b ; } __attribute__ ( ( transparent_union ) ) ; // expected-error {{field has incomplete type 'struct stb'}}
2017-03-01 04:44:39 +08:00
typedef union __attribute__ ( ( __transparent_union__ ) ) {
int * i ;
struct st * s ;
} TU6 ;
void bar ( TU6 ) ;
void foo11 ( int * i ) {
bar ( i ) ;
}
void foo2 ( struct st * s ) {
bar ( s ) ;
}