blob: 5eaa3eb2d85e35c15a974711ada0cec5e0c7f435 [file] [log] [blame]
// RUN: %clang_cc1 %s -std=c++23 -triple=x86_64-apple-darwin10 -fsyntax-only -verify=expected,bitfieldwarnings,cpp -Wno-unused-value -Wno-unused-but-set-variable -Wbitfield-width -Wbitfield-enum-conversion
// RUN: %clang_cc1 %s -std=c++23 -triple=x86_64-apple-darwin10 -fsyntax-only -verify=expected,cpp -Wno-unused-value -Wno-unused-but-set-variable
// RUN: %clang_cc1 %s -x c -std=c23 -triple=x86_64-apple-darwin10 -fsyntax-only -verify=expected,c -Wno-unused-value -Wno-unused-but-set-variable
// RUN: %clang_cc1 %s -x c -std=c23 -triple=x86_64-apple-darwin10 -fsyntax-only -verify=expected,bitfieldwarnings,c -Wno-unused-value -Wno-unused-but-set-variable -Wbitfield-width -Wbitfield-enum-conversion
typedef enum A {
A_a,
A_b,
A_c,
A_d
} A;
#ifdef __cplusplus
#define DEFINE_ENUM(_Name, _Type, ...) enum class _Name : _Type { __VA_ARGS__ } ;
#define ENUM_CLASS_REF(_Name, _Enum) _Name::_Enum
#else
#define DEFINE_ENUM(_Name, _Type, ...) typedef enum _Name : _Type { __VA_ARGS__ } _Name;
#define ENUM_CLASS_REF(_Name, _Enum) _Enum
#endif
DEFINE_ENUM(B, int, B_a, B_b, B_c, B_d );
DEFINE_ENUM(C, unsigned, C_a, C_b, C_c, C_d );
DEFINE_ENUM(D, unsigned, D_a, D_b);
// Not using templates here so we can more easily distinguish the responsible
// party for each warning
typedef struct S_A {
A field1 : 1; // #S_A_field1
A field2 : 2; // #S_A_field2
A field3 : 8; // #S_A_field3
__attribute__((preferred_type(A))) // #preferred_S_A_field4
unsigned field4 : 1; // #S_A_field4
__attribute__((preferred_type(A)))
unsigned field5 : 2; // #S_A_field5
__attribute__((preferred_type(A)))
unsigned field6 : 8; // #S_A_field6
__attribute__((preferred_type(A))) // #preferred_S_A_field7
int field7 : 1; // #S_A_field7
__attribute__((preferred_type(A))) // #preferred_S_A_field8
int field8 : 2; // #S_A_field8
__attribute__((preferred_type(A)))
int field9 : 8; // #S_A_field9
__attribute__((preferred_type(A)))
D field10 : 1; // #S_A_field10
__attribute__((preferred_type(A))) // #preferred_S_A_field11
D field11 : 2; // #S_A_field11
__attribute__((preferred_type(A)))
D field12 : 8; // #S_A_field12
} S_A;
typedef struct S_B {
B field1 : 1; // #S_B_field1
B field2 : 2; // #S_B_field2
B field3 : 8; // #S_B_field3
__attribute__((preferred_type(B))) // #preferred_S_B_field4
unsigned field4 : 1; // #S_B_field4
__attribute__((preferred_type(B)))
unsigned field5 : 2; // #S_B_field5
__attribute__((preferred_type(B)))
unsigned field6 : 8; // #S_B_field6
__attribute__((preferred_type(B))) // #preferred_S_B_field7
int field7 : 1; // #S_B_field7
__attribute__((preferred_type(B))) // #preferred_S_B_field8
int field8 : 2; // #S_B_field8
__attribute__((preferred_type(B)))
int field9 : 8; // #S_B_field9
__attribute__((preferred_type(B)))
D field10 : 1; // #S_B_field10
__attribute__((preferred_type(B))) // #preferred_S_B_field11
D field11 : 2; // #S_B_field11
__attribute__((preferred_type(B)))
D field12 : 8; // #S_B_field12
} S_B;
typedef struct S_C {
C field1 : 1; // #S_C_field1
C field2 : 2; // #S_C_field2
C field3 : 8; // #S_C_field3
__attribute__((preferred_type(C))) // #preferred_S_C_field4
unsigned field4 : 1; // #S_C_field4
__attribute__((preferred_type(C)))
unsigned field5 : 2; // #S_C_field5
__attribute__((preferred_type(C)))
unsigned field6 : 8; // #S_C_field6
__attribute__((preferred_type(C))) // #preferred_S_C_field7
int field7 : 1; // #S_C_field7
__attribute__((preferred_type(C))) // #preferred_S_C_field8
int field8 : 2; // #S_C_field8
__attribute__((preferred_type(C)))
int field9 : 8; // #S_C_field9
__attribute__((preferred_type(C)))
D field10 : 1; // #S_C_field10
__attribute__((preferred_type(C))) // #preferred_S_C_field11
D field11 : 2; // #S_C_field11
__attribute__((preferred_type(C)))
D field12 : 8; // #S_C_field12
} S_C;
void read_enumA(S_A *s) {
A x;
x = s->field1;
x = s->field2;
x = s->field3;
x = (A)s->field4;
x = (A)s->field5;
x = (A)s->field6;
x = (A)s->field7;
x = (A)s->field8;
x = (A)s->field9;
x = (A)s->field10;
x = (A)s->field11;
x = (A)s->field12;
}
void read_enumB(S_B *s) {
B x;
x = s->field1;
x = s->field2;
x = s->field3;
x = (B)s->field4;
x = (B)s->field5;
x = (B)s->field6;
x = (B)s->field7;
x = (B)s->field8;
x = (B)s->field9;
x = (B)s->field10;
x = (B)s->field11;
x = (B)s->field12;
}
void read_enumC(S_C *s) {
C x;
x = s->field1;
x = s->field2;
x = s->field3;
x = (C)s->field4;
x = (C)s->field5;
x = (C)s->field6;
x = (C)s->field7;
x = (C)s->field8;
x = (C)s->field9;
x = (C)s->field10;
x = (C)s->field11;
x = (C)s->field12;
}
void write_enumA(S_A *s, A x) {
s->field1 = x;
// bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to store all enumerators of 'A'}}
// bitfieldwarnings-note@#S_A_field1 {{widen this field to 2 bits to store all values of 'A'}}
s->field2 = x;
s->field3 = x;
s->field4 = x;
// bitfieldwarnings-warning@-1 {{bit-field 'field4' is not wide enough to store all enumerators of 'A'}}
// bitfieldwarnings-note@#S_A_field4 {{widen this field to 2 bits to store all values of 'A'}}
s->field5 = x;
s->field6 = x;
s->field7 = x;
// bitfieldwarnings-warning@-1 {{bit-field 'field7' is not wide enough to store all enumerators of 'A'}}
// bitfieldwarnings-note@#S_A_field7 {{widen this field to 2 bits to store all values of 'A'}}
s->field8 = x;
// bitfieldwarnings-warning@-1 {{signed bit-field 'field8' needs an extra bit to represent the largest positive enumerators of 'A'}}
// bitfieldwarnings-note@#S_A_field8 {{consider making the bit-field type unsigned}}
s->field9 = x;
s->field10 = (D)x;
s->field11 = (D)x;
s->field12 = (D)x;
}
void write_enumB(S_B *s, B x) {
s->field1 = x;
// bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to store all enumerators of 'B'}}
// bitfieldwarnings-note@#S_B_field1 {{widen this field to 2 bits to store all values of 'B'}}
s->field2 = x;
// bitfieldwarnings-warning@-1 {{signed bit-field 'field2' needs an extra bit to represent the largest positive enumerators of 'B'}}
// bitfieldwarnings-note@#S_B_field2 {{consider making the bit-field type unsigned}}
s->field3 = x;
s->field4 = (unsigned)x;
// expected-warning@-1 {{bit-field 'field4' is not wide enough to store all enumerators of preferred type 'B'}}
// expected-note@#S_B_field4 {{widen this field to 2 bits to store all values of 'B'}}
// expected-note@#preferred_S_B_field4 {{preferred type for bit-field 'B' specified here}}
s->field5 = (unsigned)x;
s->field6 = (unsigned)x;
s->field7 = (int)x;
// expected-warning@-1 {{bit-field 'field7' is not wide enough to store all enumerators of preferred type 'B'}}
// expected-note@#S_B_field7 {{widen this field to 2 bits to store all values of 'B'}}
// expected-note@#preferred_S_B_field7 {{preferred type for bit-field 'B' specified here}}
s->field8 = (int)x;
// expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to represent the largest positive enumerators of preferred type 'B'}}
// expected-note@#S_B_field8 {{consider making the bit-field type unsigned}}
// expected-note@#preferred_S_B_field8 {{preferred type for bit-field 'B' specified here}}
s->field9 = (int)x;
s->field10 = (D)x;
s->field11 = (D)x;
s->field12 = (D)x;
}
void write_enumC(S_C *s, C x) {
s->field1 = x;
// bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to store all enumerators of 'C'}}
// bitfieldwarnings-note@#S_C_field1 {{widen this field to 2 bits to store all values of 'C'}}
s->field2 = x;
s->field3 = x;
s->field4 = (unsigned)x;
// expected-warning@-1 {{bit-field 'field4' is not wide enough to store all enumerators of preferred type 'C'}}
// expected-note@#S_C_field4 {{widen this field to 2 bits to store all values of 'C'}}
// expected-note@#preferred_S_C_field4 {{preferred type for bit-field 'C' specified here}}
s->field5 = (unsigned)x;
s->field6 = (unsigned)x;
s->field7 = (int)x;
// expected-warning@-1 {{bit-field 'field7' is not wide enough to store all enumerators of preferred type 'C'}}
// expected-note@#S_C_field7 {{widen this field to 2 bits to store all values of 'C'}}
// expected-note@#preferred_S_C_field7 {{preferred type for bit-field 'C' specified here}}
s->field8 = (int)x;
// expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to represent the largest positive enumerators of preferred type 'C'}}
// expected-note@#S_C_field8 {{consider making the bit-field type unsigned}}
// expected-note@#preferred_S_C_field8 {{preferred type for bit-field 'C' specified here}}
s->field9 = (int)x;
s->field10 = (D)x;
s->field11 = (D)x;
s->field12 = (D)x;
}
void write_enum_intA(struct S_A *s, int x) {
s->field1 = (A)x;
// bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to store all enumerators of 'A'}}
// bitfieldwarnings-note@#S_A_field1 {{widen this field to 2 bits to store all values of 'A'}}
s->field2 = (A)x;
s->field3 = (A)x;
s->field4 = x;
// expected-warning@-1 {{bit-field 'field4' is not wide enough to store all enumerators of preferred type 'A'}}
// expected-note@#S_A_field4 {{widen this field to 2 bits to store all values of 'A'}}
// expected-note@#preferred_S_A_field4 {{preferred type for bit-field 'A' specified here}}
s->field5 = x;
s->field6 = x;
s->field7 = x;
// expected-warning@-1 {{bit-field 'field7' is not wide enough to store all enumerators of preferred type 'A'}}
// expected-note@#S_A_field7 {{widen this field to 2 bits to store all values of 'A'}}
// expected-note@#preferred_S_A_field7 {{preferred type for bit-field 'A' specified here}}
s->field8 = x;
// expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to represent the largest positive enumerators of preferred type 'A'}}
// expected-note@#S_A_field8 {{consider making the bit-field type unsigned}}
// expected-note@#preferred_S_A_field8 {{preferred type for bit-field 'A' specified here}}
s->field9 = x;
s->field10 = (D)x;
s->field11 = (D)x;
s->field12 = (D)x;
}
void write_enum_intB(struct S_B *s, int x) {
s->field1 = (B)x;
// bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to store all enumerators of 'B'}}
// bitfieldwarnings-note@#S_B_field1 {{widen this field to 2 bits to store all values of 'B'}}
s->field2 = (B)x;
// bitfieldwarnings-warning@-1 {{signed bit-field 'field2' needs an extra bit to represent the largest positive enumerators of 'B'}}
// bitfieldwarnings-note@#S_B_field2 {{consider making the bit-field type unsigned}}
s->field3 = (B)x;
s->field4 = x;
// expected-warning@-1 {{bit-field 'field4' is not wide enough to store all enumerators of preferred type 'B'}}
// expected-note@#S_B_field4 {{widen this field to 2 bits to store all values of 'B'}}
// expected-note@#preferred_S_B_field4 {{preferred type for bit-field 'B' specified here}}
s->field5 = x;
s->field6 = x;
s->field7 = x;
// expected-warning@-1 {{bit-field 'field7' is not wide enough to store all enumerators of preferred type 'B'}}
// expected-note@#S_B_field7 {{widen this field to 2 bits to store all values of 'B'}}
// expected-note@#preferred_S_B_field7 {{preferred type for bit-field 'B' specified here}}
s->field8 = x;
// expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to represent the largest positive enumerators of preferred type 'B'}}
// expected-note@#S_B_field8 {{consider making the bit-field type unsigned}}
// expected-note@#preferred_S_B_field8 {{preferred type for bit-field 'B' specified here}}
s->field9 = x;
s->field10 = (D)x;
s->field11 = (D)x;
s->field12 = (D)x;
}
void write_enum_intC(struct S_C *s, int x) {
s->field1 = (C)x;
// bitfieldwarnings-warning@-1 {{bit-field 'field1' is not wide enough to store all enumerators of 'C'}}
// bitfieldwarnings-note@#S_C_field1 {{widen this field to 2 bits to store all values of 'C'}}
s->field2 = (C)x;
s->field3 = (C)x;
s->field4 = x;
// expected-warning@-1 {{bit-field 'field4' is not wide enough to store all enumerators of preferred type 'C'}}
// expected-note@#S_C_field4 {{widen this field to 2 bits to store all values of 'C'}}
// expected-note@#preferred_S_C_field4 {{preferred type for bit-field 'C' specified here}}
s->field5 = x;
s->field6 = x;
s->field7 = x;
// expected-warning@-1 {{bit-field 'field7' is not wide enough to store all enumerators of preferred type 'C'}}
// expected-note@#S_C_field7 {{widen this field to 2 bits to store all values of 'C'}}
// expected-note@#preferred_S_C_field7 {{preferred type for bit-field 'C' specified here}}
s->field8 = x;
// expected-warning@-1 {{signed bit-field 'field8' needs an extra bit to represent the largest positive enumerators of preferred type 'C'}}
// expected-note@#S_C_field8 {{consider making the bit-field type unsigned}}
// expected-note@#preferred_S_C_field8 {{preferred type for bit-field 'C' specified here}}
s->field9 = x;
s->field10 = (D)x;
s->field11 = (D)x;
s->field12 = (D)x;
}
void write_low_constantA(S_A *s) {
s->field1 = A_a;
s->field2 = A_a;
s->field3 = A_a;
s->field4 = A_a;
s->field5 = A_a;
s->field6 = A_a;
s->field7 = A_a;
s->field8 = A_a;
s->field9 = A_a;
s->field10 = (D)A_a;
s->field11 = (D)A_a;
s->field12 = (D)A_a;
};
void write_low_constantB(S_B *s) {
s->field1 = ENUM_CLASS_REF(B, B_a);
s->field2 = ENUM_CLASS_REF(B, B_a);
s->field3 = ENUM_CLASS_REF(B, B_a);
s->field4 = (unsigned)ENUM_CLASS_REF(B, B_a);
s->field5 = (unsigned)ENUM_CLASS_REF(B, B_a);
s->field6 = (unsigned)ENUM_CLASS_REF(B, B_a);
s->field7 = (int)ENUM_CLASS_REF(B, B_a);
s->field8 = (int)ENUM_CLASS_REF(B, B_a);
s->field9 = (int)ENUM_CLASS_REF(B, B_a);
s->field10 = (D)ENUM_CLASS_REF(B, B_a);
s->field11 = (D)ENUM_CLASS_REF(B, B_a);
s->field12 = (D)ENUM_CLASS_REF(B, B_a);
};
void write_low_constantC(S_C *s) {
s->field1 = ENUM_CLASS_REF(C, C_a);
s->field2 = ENUM_CLASS_REF(C, C_a);
s->field3 = ENUM_CLASS_REF(C, C_a);
s->field4 = (unsigned)ENUM_CLASS_REF(C, C_a);
s->field5 = (unsigned)ENUM_CLASS_REF(C, C_a);
s->field6 = (unsigned)ENUM_CLASS_REF(C, C_a);
s->field7 = (int)ENUM_CLASS_REF(C, C_a);
s->field8 = (int)ENUM_CLASS_REF(C, C_a);
s->field9 = (int)ENUM_CLASS_REF(C, C_a);
s->field10 = (D)ENUM_CLASS_REF(C, C_a);
s->field11 = (D)ENUM_CLASS_REF(C, C_a);
s->field12 = (D)ENUM_CLASS_REF(C, C_a);
};
void write_high_constantA(S_A *s) {
s->field1 = A_d;
// cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value from 3 to 1}}
// c-warning@-2 {{implicit truncation from 'int' to bit-field changes value from 3 to 1}}
s->field2 = A_d;
s->field3 = A_d;
s->field4 = A_d;
// cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value from 3 to 1}}
// c-warning@-2 {{implicit truncation from 'int' to bit-field changes value from 3 to 1}}
s->field5 = A_d;
s->field6 = A_d;
s->field7 = A_d;
// cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value from 3 to -1}}
// c-warning@-2 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field8 = A_d;
// cpp-warning@-1 {{implicit truncation from 'A' to bit-field changes value from 3 to -1}}
// c-warning@-2 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field9 = A_d;
s->field10 = (D)A_d;
// cpp-warning@-1 {{implicit truncation from 'D' to bit-field changes value from 3 to 1}}
// c-warning@-2 {{implicit truncation from 'D' (aka 'enum D') to bit-field changes value from 3 to 1}}
s->field11 = (D)A_d;
s->field12 = (D)A_d;
};
void write_high_constantB(S_B *s) {
s->field1 = ENUM_CLASS_REF(B, B_d);
// cpp-warning@-1 {{implicit truncation from 'B' to bit-field changes value from 3 to 1}}
// c-warning@-2 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field2 = ENUM_CLASS_REF(B, B_d);
// c-warning@-1 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field3 = ENUM_CLASS_REF(B, B_d);
s->field4 = (unsigned)ENUM_CLASS_REF(B, B_d);
// expected-warning@-1 {{implicit truncation from 'unsigned int' to bit-field changes value from 3 to 1}}
s->field5 = (unsigned)ENUM_CLASS_REF(B, B_d);
s->field6 = (unsigned)ENUM_CLASS_REF(B, B_d);
s->field7 = (int)ENUM_CLASS_REF(B, B_d);
// expected-warning@-1 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field8 = (int)ENUM_CLASS_REF(B, B_d);
// expected-warning@-1 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field9 = (int)ENUM_CLASS_REF(B, B_d);
};
void write_high_constantC(S_C *s) {
s->field1 = ENUM_CLASS_REF(C, C_d);
// cpp-warning@-1 {{implicit truncation from 'C' to bit-field changes value from 3 to 1}}
// c-warning@-2 {{implicit truncation from 'unsigned int' to bit-field changes value from 3 to 1}}
s->field2 = ENUM_CLASS_REF(C, C_d);
s->field3 = ENUM_CLASS_REF(C, C_d);
s->field4 = (unsigned)ENUM_CLASS_REF(C, C_d);
// expected-warning@-1 {{implicit truncation from 'unsigned int' to bit-field changes value from 3 to 1}}
s->field5 = (unsigned)ENUM_CLASS_REF(C, C_d);
s->field6 = (unsigned)ENUM_CLASS_REF(C, C_d);
s->field7 = (int)ENUM_CLASS_REF(C, C_d);
// expected-warning@-1 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field8 = (int)ENUM_CLASS_REF(C, C_d);
// expected-warning@-1 {{implicit truncation from 'int' to bit-field changes value from 3 to -1}}
s->field9 = (int)ENUM_CLASS_REF(C, C_d);
};